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() */
41 #define JNLIB_NEED_LOG_LOGV
45 #include "get-passphrase.h"
50 enum cmd_and_opt_values
81 struct rsa_secret_key_s
83 gcry_mpi_t n
; /* public modulus */
84 gcry_mpi_t e
; /* public exponent */
85 gcry_mpi_t d
; /* exponent */
86 gcry_mpi_t p
; /* prime p. */
87 gcry_mpi_t q
; /* prime q. */
88 gcry_mpi_t u
; /* inverse of p mod q. */
92 static const char *opt_homedir
;
94 static int opt_canonical
;
97 static int opt_no_fail_on_exist
;
98 static int opt_have_cert
;
99 static const char *opt_passphrase
;
100 static char *opt_prompt
;
101 static int opt_status_msg
;
102 static const char *opt_p12_charset
;
103 static const char *opt_agent_program
;
105 static char *get_passphrase (int promptno
);
106 static void release_passphrase (char *pw
);
107 static int store_private_key (const unsigned char *grip
,
108 const void *buffer
, size_t length
, int force
);
111 static ARGPARSE_OPTS opts
[] = {
112 ARGPARSE_group (300, N_("@Commands:\n ")),
114 ARGPARSE_c (oProtect
, "protect", "protect a private key"),
115 ARGPARSE_c (oUnprotect
, "unprotect", "unprotect a private key"),
116 ARGPARSE_c (oShadow
, "shadow", "create a shadow entry for a public key"),
117 ARGPARSE_c (oShowShadowInfo
, "show-shadow-info", "return the shadow info"),
118 ARGPARSE_c (oShowKeygrip
, "show-keygrip", "show the \"keygrip\""),
119 ARGPARSE_c (oP12Import
, "p12-import",
120 "import a pkcs#12 encoded private key"),
121 ARGPARSE_c (oP12Export
, "p12-export",
122 "export a private key pkcs#12 encoded"),
124 ARGPARSE_group (301, N_("@\nOptions:\n ")),
126 ARGPARSE_s_n (oVerbose
, "verbose", "verbose"),
127 ARGPARSE_s_n (oArmor
, "armor", "write output in advanced format"),
128 ARGPARSE_s_n (oCanonical
, "canonical", "write output in canonical format"),
130 ARGPARSE_s_s (oPassphrase
, "passphrase", "|STRING|use passphrase STRING"),
131 ARGPARSE_s_s (oP12Charset
,"p12-charset",
132 "|NAME|set charset for a new PKCS#12 passphrase to NAME"),
133 ARGPARSE_s_n (oHaveCert
, "have-cert",
134 "certificate to export provided on STDIN"),
135 ARGPARSE_s_n (oStore
, "store",
136 "store the created key in the appropriate place"),
137 ARGPARSE_s_n (oForce
, "force",
138 "force overwriting"),
139 ARGPARSE_s_n (oNoFailOnExist
, "no-fail-on-exist", "@"),
140 ARGPARSE_s_s (oHomedir
, "homedir", "@"),
141 ARGPARSE_s_s (oPrompt
, "prompt",
142 "|ESCSTRING|use ESCSTRING as prompt in pinentry"),
143 ARGPARSE_s_n (oStatusMsg
, "enable-status-msg", "@"),
145 ARGPARSE_s_s (oAgentProgram
, "agent-program", "@"),
151 my_strusage (int level
)
156 case 11: p
= "gpg-protect-tool (GnuPG)";
158 case 13: p
= VERSION
; break;
159 case 17: p
= PRINTABLE_OS_NAME
; break;
160 case 19: p
= _("Please report bugs to <@EMAIL@>.\n"); break;
163 case 40: p
= _("Usage: gpg-protect-tool [options] (-h for help)\n");
165 case 41: p
= _("Syntax: gpg-protect-tool [options] [args]\n"
166 "Secret key maintenance tool\n");
176 /* print_mpi (const char *text, gcry_mpi_t a) */
179 /* void *bufaddr = &buf; */
182 /* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */
184 /* log_info ("%s: [error printing number: %s]\n", text, gpg_strerror (rc)); */
187 /* log_info ("%s: %s\n", text, buf); */
188 /* gcry_free (buf); */
194 static unsigned char *
195 make_canonical (const char *fname
, const char *buf
, size_t buflen
)
200 unsigned char *result
;
202 rc
= gcry_sexp_sscan (&sexp
, &erroff
, buf
, buflen
);
205 log_error ("invalid S-Expression in `%s' (off=%u): %s\n",
206 fname
, (unsigned int)erroff
, gpg_strerror (rc
));
209 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_CANON
, NULL
, 0);
211 result
= xmalloc (len
);
212 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_CANON
, result
, len
);
214 gcry_sexp_release (sexp
);
219 make_advanced (const unsigned char *buf
, size_t buflen
)
226 rc
= gcry_sexp_sscan (&sexp
, &erroff
, (const char*)buf
, buflen
);
229 log_error ("invalid canonical S-Expression (off=%u): %s\n",
230 (unsigned int)erroff
, gpg_strerror (rc
));
233 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_ADVANCED
, NULL
, 0);
235 result
= xmalloc (len
);
236 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_ADVANCED
, result
, len
);
238 gcry_sexp_release (sexp
);
244 read_file (const char *fname
, size_t *r_length
)
250 if (!strcmp (fname
, "-"))
252 size_t nread
, bufsize
= 0;
255 #ifdef HAVE_DOSISH_SYSTEM
256 setmode ( fileno(fp
) , O_BINARY
);
265 buf
= xmalloc (bufsize
);
267 buf
= xrealloc (buf
, bufsize
);
269 nread
= fread (buf
+buflen
, 1, NCHUNK
, fp
);
270 if (nread
< NCHUNK
&& ferror (fp
))
272 log_error ("error reading `[stdin]': %s\n", strerror (errno
));
278 while (nread
== NCHUNK
);
286 fp
= fopen (fname
, "rb");
289 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
293 if (fstat (fileno(fp
), &st
))
295 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
301 buf
= xmalloc (buflen
+1);
302 if (fread (buf
, buflen
, 1, fp
) != 1)
304 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
317 static unsigned char *
318 read_key (const char *fname
)
324 buf
= read_file (fname
, &buflen
);
327 key
= make_canonical (fname
, buf
, buflen
);
335 read_and_protect (const char *fname
)
339 unsigned char *result
;
343 key
= read_key (fname
);
347 pw
= get_passphrase (1);
348 rc
= agent_protect (key
, pw
, &result
, &resultlen
);
349 release_passphrase (pw
);
353 log_error ("protecting the key failed: %s\n", gpg_strerror (rc
));
359 char *p
= make_advanced (result
, resultlen
);
363 result
= (unsigned char*)p
;
364 resultlen
= strlen (p
);
367 fwrite (result
, resultlen
, 1, stdout
);
373 read_and_unprotect (const char *fname
)
377 unsigned char *result
;
380 gnupg_isotime_t protected_at
;
382 key
= read_key (fname
);
386 rc
= agent_unprotect (key
, (pw
=get_passphrase (1)),
387 protected_at
, &result
, &resultlen
);
388 release_passphrase (pw
);
393 log_info ("[PROTECT-TOOL:] bad-passphrase\n");
394 log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc
));
398 log_info ("key protection done at %.4s-%.2s-%.2s %.2s:%.2s:%s\n",
399 protected_at
, protected_at
+4, protected_at
+6,
400 protected_at
+9, protected_at
+11, protected_at
+13);
405 char *p
= make_advanced (result
, resultlen
);
409 result
= (unsigned char*)p
;
410 resultlen
= strlen (p
);
413 fwrite (result
, resultlen
, 1, stdout
);
420 read_and_shadow (const char *fname
)
424 unsigned char *result
;
426 unsigned char dummy_info
[] = "(8:313233342:43)";
428 key
= read_key (fname
);
432 rc
= agent_shadow_key (key
, dummy_info
, &result
);
436 log_error ("shadowing the key failed: %s\n", gpg_strerror (rc
));
439 resultlen
= gcry_sexp_canon_len (result
, 0, NULL
,NULL
);
444 char *p
= make_advanced (result
, resultlen
);
448 result
= (unsigned char*)p
;
449 resultlen
= strlen (p
);
452 fwrite (result
, resultlen
, 1, stdout
);
457 show_shadow_info (const char *fname
)
461 const unsigned char *info
;
464 key
= read_key (fname
);
468 rc
= agent_get_shadow_info (key
, &info
);
472 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc
));
475 infolen
= gcry_sexp_canon_len (info
, 0, NULL
,NULL
);
480 char *p
= make_advanced (info
, infolen
);
483 fwrite (p
, strlen (p
), 1, stdout
);
487 fwrite (info
, infolen
, 1, stdout
);
492 show_file (const char *fname
)
498 key
= read_key (fname
);
502 keylen
= gcry_sexp_canon_len (key
, 0, NULL
,NULL
);
507 fwrite (key
, keylen
, 1, stdout
);
511 p
= make_advanced (key
, keylen
);
514 fwrite (p
, strlen (p
), 1, stdout
);
522 show_keygrip (const char *fname
)
526 unsigned char grip
[20];
529 key
= read_key (fname
);
533 if (gcry_sexp_new (&private, key
, 0, 0))
535 log_error ("gcry_sexp_new failed\n");
540 if (!gcry_pk_get_keygrip (private, grip
))
542 log_error ("can't calculate keygrip\n");
545 gcry_sexp_release (private);
547 for (i
=0; i
< 20; i
++)
548 printf ("%02X", grip
[i
]);
554 rsa_key_check (struct rsa_secret_key_s
*skey
)
557 gcry_mpi_t t
= gcry_mpi_snew (0);
558 gcry_mpi_t t1
= gcry_mpi_snew (0);
559 gcry_mpi_t t2
= gcry_mpi_snew (0);
560 gcry_mpi_t phi
= gcry_mpi_snew (0);
562 /* check that n == p * q */
563 gcry_mpi_mul (t
, skey
->p
, skey
->q
);
564 if (gcry_mpi_cmp( t
, skey
->n
) )
566 log_error ("RSA oops: n != p * q\n");
570 /* check that p is less than q */
571 if (gcry_mpi_cmp (skey
->p
, skey
->q
) > 0)
575 log_info ("swapping secret primes\n");
576 tmp
= gcry_mpi_copy (skey
->p
);
577 gcry_mpi_set (skey
->p
, skey
->q
);
578 gcry_mpi_set (skey
->q
, tmp
);
579 gcry_mpi_release (tmp
);
580 /* and must recompute u of course */
581 gcry_mpi_invm (skey
->u
, skey
->p
, skey
->q
);
584 /* check that e divides neither p-1 nor q-1 */
585 gcry_mpi_sub_ui (t
, skey
->p
, 1 );
586 gcry_mpi_div (NULL
, t
, t
, skey
->e
, 0);
587 if (!gcry_mpi_cmp_ui( t
, 0) )
589 log_error ("RSA oops: e divides p-1\n");
592 gcry_mpi_sub_ui (t
, skey
->q
, 1);
593 gcry_mpi_div (NULL
, t
, t
, skey
->e
, 0);
594 if (!gcry_mpi_cmp_ui( t
, 0))
596 log_info ( "RSA oops: e divides q-1\n" );
600 /* check that d is correct. */
601 gcry_mpi_sub_ui (t1
, skey
->p
, 1);
602 gcry_mpi_sub_ui (t2
, skey
->q
, 1);
603 gcry_mpi_mul (phi
, t1
, t2
);
604 gcry_mpi_invm (t
, skey
->e
, phi
);
605 if (gcry_mpi_cmp (t
, skey
->d
))
606 { /* no: try universal exponent. */
607 gcry_mpi_gcd (t
, t1
, t2
);
608 gcry_mpi_div (t
, NULL
, phi
, t
, 0);
609 gcry_mpi_invm (t
, skey
->e
, t
);
610 if (gcry_mpi_cmp (t
, skey
->d
))
612 log_error ("RSA oops: bad secret exponent\n");
617 /* check for correctness of u */
618 gcry_mpi_invm (t
, skey
->p
, skey
->q
);
619 if (gcry_mpi_cmp (t
, skey
->u
))
621 log_info ( "RSA oops: bad u parameter\n");
626 log_info ("RSA secret key check failed\n");
628 gcry_mpi_release (t
);
629 gcry_mpi_release (t1
);
630 gcry_mpi_release (t2
);
631 gcry_mpi_release (phi
);
637 /* A callback used by p12_parse to return a certificate. */
639 import_p12_cert_cb (void *opaque
, const unsigned char *cert
, size_t certlen
)
641 struct b64state state
;
642 gpg_error_t err
, err2
;
646 err
= b64enc_start (&state
, stdout
, "CERTIFICATE");
648 err
= b64enc_write (&state
, cert
, certlen
);
649 err2
= b64enc_finish (&state
);
653 log_error ("error writing armored certificate: %s\n", gpg_strerror (err
));
657 import_p12_file (const char *fname
)
660 unsigned char *result
;
661 size_t buflen
, resultlen
, buf_off
;
665 struct rsa_secret_key_s sk
;
668 unsigned char grip
[20];
671 /* fixme: we should release some stuff on error */
673 buf
= read_file (fname
, &buflen
);
677 /* GnuPG 2.0.4 accidently created binary P12 files with the string
678 "The passphrase is %s encoded.\n\n" prepended to the ASN.1 data.
680 if (buflen
> 29 && !memcmp (buf
, "The passphrase is ", 18))
682 for (buf_off
=18; buf_off
< buflen
&& buf
[buf_off
] != '\n'; buf_off
++)
685 if (buf_off
< buflen
&& buf
[buf_off
] == '\n')
691 kparms
= p12_parse ((unsigned char*)buf
+buf_off
, buflen
-buf_off
,
692 (pw
=get_passphrase (2)),
693 import_p12_cert_cb
, NULL
);
694 release_passphrase (pw
);
698 log_error ("error parsing or decrypting the PKCS-12 file\n");
701 for (i
=0; kparms
[i
]; i
++)
705 log_error ("invalid structure of private key\n");
710 /* print_mpi (" n", kparms[0]); */
711 /* print_mpi (" e", kparms[1]); */
712 /* print_mpi (" d", kparms[2]); */
713 /* print_mpi (" p", kparms[3]); */
714 /* print_mpi (" q", kparms[4]); */
715 /* print_mpi ("dmp1", kparms[5]); */
716 /* print_mpi ("dmq1", kparms[6]); */
717 /* print_mpi (" u", kparms[7]); */
725 if (rsa_key_check (&sk
))
727 /* print_mpi (" n", sk.n); */
728 /* print_mpi (" e", sk.e); */
729 /* print_mpi (" d", sk.d); */
730 /* print_mpi (" p", sk.p); */
731 /* print_mpi (" q", sk.q); */
732 /* print_mpi (" u", sk.u); */
734 /* Create an S-expresion from the parameters. */
735 rc
= gcry_sexp_build (&s_key
, NULL
,
736 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
737 sk
.n
, sk
.e
, sk
.d
, sk
.p
, sk
.q
, sk
.u
, NULL
);
738 for (i
=0; i
< 8; i
++)
739 gcry_mpi_release (kparms
[i
]);
743 log_error ("failed to created S-expression from key: %s\n",
748 /* Compute the keygrip. */
749 if (!gcry_pk_get_keygrip (s_key
, grip
))
751 log_error ("can't calculate keygrip\n");
754 log_info ("keygrip: ");
755 for (i
=0; i
< 20; i
++)
756 log_printf ("%02X", grip
[i
]);
759 /* Convert to canonical encoding. */
760 buflen
= gcry_sexp_sprint (s_key
, GCRYSEXP_FMT_CANON
, NULL
, 0);
762 key
= gcry_xmalloc_secure (buflen
);
763 buflen
= gcry_sexp_sprint (s_key
, GCRYSEXP_FMT_CANON
, key
, buflen
);
765 gcry_sexp_release (s_key
);
767 pw
= get_passphrase (4);
768 rc
= agent_protect (key
, pw
, &result
, &resultlen
);
769 release_passphrase (pw
);
773 log_error ("protecting the key failed: %s\n", gpg_strerror (rc
));
779 char *p
= make_advanced (result
, resultlen
);
783 result
= (unsigned char*)p
;
784 resultlen
= strlen (p
);
788 store_private_key (grip
, result
, resultlen
, opt_force
);
790 fwrite (result
, resultlen
, 1, stdout
);
798 sexp_to_kparms (gcry_sexp_t sexp
)
800 gcry_sexp_t list
, l2
;
808 list
= gcry_sexp_find_token (sexp
, "private-key", 0 );
811 l2
= gcry_sexp_cadr (list
);
812 gcry_sexp_release (list
);
814 name
= gcry_sexp_nth_data (list
, 0, &n
);
815 if(!name
|| n
!= 3 || memcmp (name
, "rsa", 3))
817 gcry_sexp_release (list
);
821 /* Parameter names used with RSA. */
823 array
= xcalloc (strlen(elems
) + 1, sizeof *array
);
824 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
826 l2
= gcry_sexp_find_token (list
, s
, 1);
829 for (i
=0; i
<idx
; i
++)
830 gcry_mpi_release (array
[i
]);
832 gcry_sexp_release (list
);
833 return NULL
; /* required parameter not found */
835 array
[idx
] = gcry_sexp_nth_mpi (l2
, 1, GCRYMPI_FMT_USG
);
836 gcry_sexp_release (l2
);
839 for (i
=0; i
<idx
; i
++)
840 gcry_mpi_release (array
[i
]);
842 gcry_sexp_release (list
);
843 return NULL
; /* required parameter is invalid */
847 gcry_sexp_release (list
);
852 /* Check whether STRING is a KEYGRIP, i.e has the correct length and
853 does only consist of uppercase hex characters. */
855 is_keygrip (const char *string
)
859 for(i
=0; string
[i
] && i
< 41; i
++)
860 if (!strchr("01234567890ABCDEF", string
[i
]))
867 export_p12_file (const char *fname
)
870 gcry_mpi_t kparms
[9], *kp
;
874 struct rsa_secret_key_s sk
;
876 unsigned char *cert
= NULL
;
879 size_t keylen_for_wipe
= 0;
882 if ( is_keygrip (fname
) )
884 char hexgrip
[40+4+1];
887 assert (strlen(fname
) == 40);
888 strcpy (stpcpy (hexgrip
, fname
), ".key");
890 p
= make_filename (opt_homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
895 key
= read_key (fname
);
900 keytype
= agent_private_key_type (key
);
901 if (keytype
== PRIVATE_KEY_PROTECTED
)
903 unsigned char *tmpkey
;
906 rc
= agent_unprotect (key
, (pw
=get_passphrase (1)),
907 NULL
, &tmpkey
, &tmplen
);
908 release_passphrase (pw
);
911 if (opt_status_msg
&& gpg_err_code (rc
) == GPG_ERR_BAD_PASSPHRASE
)
912 log_info ("[PROTECT-TOOL:] bad-passphrase\n");
913 log_error ("unprotecting key `%s' failed: %s\n",
914 fname
, gpg_strerror (rc
));
920 keylen_for_wipe
= tmplen
;
922 keytype
= agent_private_key_type (key
);
925 if (keytype
== PRIVATE_KEY_SHADOWED
)
927 log_error ("`%s' is a shadowed private key - can't export it\n", fname
);
928 wipememory (key
, keylen_for_wipe
);
932 else if (keytype
!= PRIVATE_KEY_CLEAR
)
934 log_error ("\%s' is not a private key\n", fname
);
935 wipememory (key
, keylen_for_wipe
);
943 cert
= (unsigned char*)read_file ("-", &certlen
);
946 wipememory (key
, keylen_for_wipe
);
953 if (gcry_sexp_new (&private, key
, 0, 0))
955 log_error ("gcry_sexp_new failed\n");
956 wipememory (key
, keylen_for_wipe
);
961 wipememory (key
, keylen_for_wipe
);
964 kp
= sexp_to_kparms (private);
965 gcry_sexp_release (private);
968 log_error ("error converting key parameters\n");
986 kparms
[5] = gcry_mpi_snew (0); /* compute d mod (p-1) */
987 gcry_mpi_sub_ui (kparms
[5], kparms
[3], 1);
988 gcry_mpi_mod (kparms
[5], sk
.d
, kparms
[5]);
989 kparms
[6] = gcry_mpi_snew (0); /* compute d mod (q-1) */
990 gcry_mpi_sub_ui (kparms
[6], kparms
[4], 1);
991 gcry_mpi_mod (kparms
[6], sk
.d
, kparms
[6]);
995 pw
= get_passphrase (3);
996 key
= p12_build (kparms
, cert
, certlen
, pw
, opt_p12_charset
, &keylen
);
997 release_passphrase (pw
);
999 for (i
=0; i
< 8; i
++)
1000 gcry_mpi_release (kparms
[i
]);
1004 #ifdef HAVE_DOSISH_SYSTEM
1005 setmode ( fileno (stdout
) , O_BINARY
);
1007 fwrite (key
, keylen
, 1, stdout
);
1014 main (int argc
, char **argv
)
1016 ARGPARSE_ARGS pargs
;
1020 set_strusage (my_strusage
);
1021 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN
);
1022 log_set_prefix ("gpg-protect-tool", 1);
1024 /* Make sure that our subsystems are ready. */
1026 init_common_subsystems ();
1028 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION
) )
1030 log_fatal( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
1031 NEED_LIBGCRYPT_VERSION
, gcry_check_version (NULL
) );
1034 setup_libgcrypt_logging ();
1035 gcry_control (GCRYCTL_INIT_SECMEM
, 16384, 0);
1038 opt_homedir
= default_homedir ();
1043 pargs
.flags
= 1; /* (do not remove the args) */
1044 while (arg_parse (&pargs
, opts
) )
1046 switch (pargs
.r_opt
)
1048 case oVerbose
: opt
.verbose
++; break;
1049 case oArmor
: opt_armor
=1; break;
1050 case oCanonical
: opt_canonical
=1; break;
1051 case oHomedir
: opt_homedir
= pargs
.r
.ret_str
; break;
1053 case oAgentProgram
: opt_agent_program
= pargs
.r
.ret_str
; break;
1055 case oProtect
: cmd
= oProtect
; break;
1056 case oUnprotect
: cmd
= oUnprotect
; break;
1057 case oShadow
: cmd
= oShadow
; break;
1058 case oShowShadowInfo
: cmd
= oShowShadowInfo
; break;
1059 case oShowKeygrip
: cmd
= oShowKeygrip
; break;
1060 case oP12Import
: cmd
= oP12Import
; break;
1061 case oP12Export
: cmd
= oP12Export
; break;
1062 case oP12Charset
: opt_p12_charset
= pargs
.r
.ret_str
; break;
1064 case oPassphrase
: opt_passphrase
= pargs
.r
.ret_str
; break;
1065 case oStore
: opt_store
= 1; break;
1066 case oForce
: opt_force
= 1; break;
1067 case oNoFailOnExist
: opt_no_fail_on_exist
= 1; break;
1068 case oHaveCert
: opt_have_cert
= 1; break;
1069 case oPrompt
: opt_prompt
= pargs
.r
.ret_str
; break;
1070 case oStatusMsg
: opt_status_msg
= 1; break;
1072 default: pargs
.err
= ARGPARSE_PRINT_ERROR
; break;
1075 if (log_get_errorcount (0))
1084 /* Set the information which can't be taken from envvars. */
1085 gnupg_prepare_get_passphrase (GPG_ERR_SOURCE_DEFAULT
,
1092 opt_prompt
= percent_plus_unescape (opt_prompt
, 0);
1094 if (cmd
== oProtect
)
1095 read_and_protect (fname
);
1096 else if (cmd
== oUnprotect
)
1097 read_and_unprotect (fname
);
1098 else if (cmd
== oShadow
)
1099 read_and_shadow (fname
);
1100 else if (cmd
== oShowShadowInfo
)
1101 show_shadow_info (fname
);
1102 else if (cmd
== oShowKeygrip
)
1103 show_keygrip (fname
);
1104 else if (cmd
== oP12Import
)
1105 import_p12_file (fname
);
1106 else if (cmd
== oP12Export
)
1107 export_p12_file (fname
);
1112 return 8; /*NOTREACHED*/
1118 rc
= rc
? rc
: log_get_errorcount(0)? 2 : 0;
1123 /* Return the passphrase string and ask the agent if it has not been
1124 set from the command line PROMPTNO select the prompt to display:
1126 1 = taken from the option --prompt
1127 2 = for unprotecting a pkcs#12 object
1128 3 = for protecting a new pkcs#12 object
1129 4 = for protecting an imported pkcs#12 in our system
1132 get_passphrase (int promptno
)
1141 return xstrdup (opt_passphrase
);
1143 orig_codeset
= i18n_switchto_utf8 ();
1145 if (promptno
== 1 && opt_prompt
)
1149 else if (promptno
== 2)
1151 desc
= _("Please enter the passphrase to unprotect the "
1154 else if (promptno
== 3)
1156 desc
= _("Please enter the passphrase to protect the "
1157 "new PKCS#12 object.");
1160 else if (promptno
== 4)
1162 desc
= _("Please enter the passphrase to protect the "
1163 "imported object within the GnuPG system.");
1167 desc
= _("Please enter the passphrase or the PIN\n"
1168 "needed to complete this operation.");
1170 i18n_switchback (orig_codeset
);
1172 err
= gnupg_get_passphrase (NULL
, NULL
, _("Passphrase:"), desc
,
1173 repeat
, repeat
, 1, &pw
);
1176 if (gpg_err_code (err
) == GPG_ERR_CANCELED
)
1177 log_info (_("cancelled\n"));
1179 log_error (_("error while asking for the passphrase: %s\n"),
1180 gpg_strerror (err
));
1190 release_passphrase (char *pw
)
1194 wipememory (pw
, strlen (pw
));
1200 store_private_key (const unsigned char *grip
,
1201 const void *buffer
, size_t length
, int force
)
1205 char hexgrip
[40+4+1];
1207 bin2hex (grip
, 20, hexgrip
);
1208 strcpy (hexgrip
+40, ".key");
1210 fname
= make_filename (opt_homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
1212 fp
= es_fopen (fname
, "wb");
1215 if (!access (fname
, F_OK
))
1218 log_info ("[PROTECT-TOOL:] secretkey-exists\n");
1219 if (opt_no_fail_on_exist
)
1220 log_info ("secret key file `%s' already exists\n", fname
);
1222 log_error ("secret key file `%s' already exists\n", fname
);
1224 return opt_no_fail_on_exist
? 0 : -1;
1226 /* FWIW: Under Windows Vista the standard fopen in the msvcrt
1227 fails if the "x" GNU extension is used. */
1228 fp
= es_fopen (fname
, "wbx");
1233 log_error ("can't create `%s': %s\n", fname
, strerror (errno
));
1238 if (es_fwrite (buffer
, length
, 1, fp
) != 1)
1240 log_error ("error writing `%s': %s\n", fname
, strerror (errno
));
1248 log_error ("error closing `%s': %s\n", fname
, strerror (errno
));
1253 log_info ("secret key stored as `%s'\n", fname
);
1256 log_info ("[PROTECT-TOOL:] secretkey-stored\n");