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
44 #include "simple-pwquery.h"
49 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_p12_charset
;
100 static char *get_passphrase (int promptno
, int opt_check
);
101 static char *get_new_passphrase (int promptno
);
102 static void release_passphrase (char *pw
);
103 static int store_private_key (const unsigned char *grip
,
104 const void *buffer
, size_t length
, int force
);
107 static ARGPARSE_OPTS opts
[] = {
109 { 301, NULL
, 0, N_("@Options:\n ") },
111 { oVerbose
, "verbose", 0, "verbose" },
112 { oArmor
, "armor", 0, "write output in advanced format" },
113 { oCanonical
, "canonical", 0, "write output in canonical format" },
114 { oPassphrase
, "passphrase", 2, "|STRING|use passphrase STRING" },
115 { oProtect
, "protect", 256, "protect a private key"},
116 { oUnprotect
, "unprotect", 256, "unprotect a private key"},
117 { oShadow
, "shadow", 256, "create a shadow entry for a public key"},
118 { oShowShadowInfo
, "show-shadow-info", 256, "return the shadow info"},
119 { oShowKeygrip
, "show-keygrip", 256, "show the \"keygrip\""},
121 { oP12Import
, "p12-import", 256, "import a pkcs#12 encoded private key"},
122 { oP12Export
, "p12-export", 256, "export a private key pkcs#12 encoded"},
123 { oP12Charset
,"p12-charset", 2,
124 "|NAME|set charset for a new PKCS#12 passphrase to NAME" },
125 { oHaveCert
, "have-cert", 0, "certificate to export provided on STDIN"},
126 { oStore
, "store", 0, "store the created key in the appropriate place"},
127 { oForce
, "force", 0, "force overwriting"},
128 { oNoFailOnExist
, "no-fail-on-exist", 0, "@" },
129 { oHomedir
, "homedir", 2, "@" },
130 { oPrompt
, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"},
131 { oStatusMsg
, "enable-status-msg", 0, "@"},
137 my_strusage (int level
)
142 case 11: p
= "gpg-protect-tool (GnuPG)";
144 case 13: p
= VERSION
; break;
145 case 17: p
= PRINTABLE_OS_NAME
; break;
146 case 19: p
= _("Please report bugs to <" PACKAGE_BUGREPORT
">.\n");
149 case 40: p
= _("Usage: gpg-protect-tool [options] (-h for help)\n");
151 case 41: p
= _("Syntax: gpg-protect-tool [options] [args]\n"
152 "Secret key maintenance tool\n");
161 /* Include the implementation of map_spwq_error. */
165 /* print_mpi (const char *text, gcry_mpi_t a) */
168 /* void *bufaddr = &buf; */
171 /* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */
173 /* log_info ("%s: [error printing number: %s]\n", text, gpg_strerror (rc)); */
176 /* log_info ("%s: %s\n", text, buf); */
177 /* gcry_free (buf); */
183 static unsigned char *
184 make_canonical (const char *fname
, const char *buf
, size_t buflen
)
189 unsigned char *result
;
191 rc
= gcry_sexp_sscan (&sexp
, &erroff
, buf
, buflen
);
194 log_error ("invalid S-Expression in `%s' (off=%u): %s\n",
195 fname
, (unsigned int)erroff
, gpg_strerror (rc
));
198 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_CANON
, NULL
, 0);
200 result
= xmalloc (len
);
201 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_CANON
, result
, len
);
203 gcry_sexp_release (sexp
);
208 make_advanced (const unsigned char *buf
, size_t buflen
)
215 rc
= gcry_sexp_sscan (&sexp
, &erroff
, (const char*)buf
, buflen
);
218 log_error ("invalid canonical S-Expression (off=%u): %s\n",
219 (unsigned int)erroff
, gpg_strerror (rc
));
222 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_ADVANCED
, NULL
, 0);
224 result
= xmalloc (len
);
225 len
= gcry_sexp_sprint (sexp
, GCRYSEXP_FMT_ADVANCED
, result
, len
);
227 gcry_sexp_release (sexp
);
233 read_file (const char *fname
, size_t *r_length
)
239 if (!strcmp (fname
, "-"))
241 size_t nread
, bufsize
= 0;
244 #ifdef HAVE_DOSISH_SYSTEM
245 setmode ( fileno(fp
) , O_BINARY
);
254 buf
= xmalloc (bufsize
);
256 buf
= xrealloc (buf
, bufsize
);
258 nread
= fread (buf
+buflen
, 1, NCHUNK
, fp
);
259 if (nread
< NCHUNK
&& ferror (fp
))
261 log_error ("error reading `[stdin]': %s\n", strerror (errno
));
267 while (nread
== NCHUNK
);
275 fp
= fopen (fname
, "rb");
278 log_error ("can't open `%s': %s\n", fname
, strerror (errno
));
282 if (fstat (fileno(fp
), &st
))
284 log_error ("can't stat `%s': %s\n", fname
, strerror (errno
));
290 buf
= xmalloc (buflen
+1);
291 if (fread (buf
, buflen
, 1, fp
) != 1)
293 log_error ("error reading `%s': %s\n", fname
, strerror (errno
));
306 static unsigned char *
307 read_key (const char *fname
)
313 buf
= read_file (fname
, &buflen
);
316 key
= make_canonical (fname
, buf
, buflen
);
324 read_and_protect (const char *fname
)
328 unsigned char *result
;
332 key
= read_key (fname
);
336 pw
= get_passphrase (1, 0);
337 rc
= agent_protect (key
, pw
, &result
, &resultlen
);
338 release_passphrase (pw
);
342 log_error ("protecting the key failed: %s\n", gpg_strerror (rc
));
348 char *p
= make_advanced (result
, resultlen
);
352 result
= (unsigned char*)p
;
353 resultlen
= strlen (p
);
356 fwrite (result
, resultlen
, 1, stdout
);
362 read_and_unprotect (const char *fname
)
366 unsigned char *result
;
369 gnupg_isotime_t protected_at
;
371 key
= read_key (fname
);
375 rc
= agent_unprotect (key
, (pw
=get_passphrase (1, 0)),
376 protected_at
, &result
, &resultlen
);
377 release_passphrase (pw
);
382 log_info ("[PROTECT-TOOL:] bad-passphrase\n");
383 log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc
));
387 log_info ("key protection done at %.4s-%.2s-%.2s %.2s:%.2s:%s\n",
388 protected_at
, protected_at
+4, protected_at
+6,
389 protected_at
+9, protected_at
+11, protected_at
+13);
394 char *p
= make_advanced (result
, resultlen
);
398 result
= (unsigned char*)p
;
399 resultlen
= strlen (p
);
402 fwrite (result
, resultlen
, 1, stdout
);
409 read_and_shadow (const char *fname
)
413 unsigned char *result
;
415 unsigned char dummy_info
[] = "(8:313233342:43)";
417 key
= read_key (fname
);
421 rc
= agent_shadow_key (key
, dummy_info
, &result
);
425 log_error ("shadowing the key failed: %s\n", gpg_strerror (rc
));
428 resultlen
= gcry_sexp_canon_len (result
, 0, NULL
,NULL
);
433 char *p
= make_advanced (result
, resultlen
);
437 result
= (unsigned char*)p
;
438 resultlen
= strlen (p
);
441 fwrite (result
, resultlen
, 1, stdout
);
446 show_shadow_info (const char *fname
)
450 const unsigned char *info
;
453 key
= read_key (fname
);
457 rc
= agent_get_shadow_info (key
, &info
);
461 log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc
));
464 infolen
= gcry_sexp_canon_len (info
, 0, NULL
,NULL
);
469 char *p
= make_advanced (info
, infolen
);
472 fwrite (p
, strlen (p
), 1, stdout
);
476 fwrite (info
, infolen
, 1, stdout
);
481 show_file (const char *fname
)
487 key
= read_key (fname
);
491 keylen
= gcry_sexp_canon_len (key
, 0, NULL
,NULL
);
496 fwrite (key
, keylen
, 1, stdout
);
500 p
= make_advanced (key
, keylen
);
503 fwrite (p
, strlen (p
), 1, stdout
);
511 show_keygrip (const char *fname
)
515 unsigned char grip
[20];
518 key
= read_key (fname
);
522 if (gcry_sexp_new (&private, key
, 0, 0))
524 log_error ("gcry_sexp_new failed\n");
529 if (!gcry_pk_get_keygrip (private, grip
))
531 log_error ("can't calculate keygrip\n");
534 gcry_sexp_release (private);
536 for (i
=0; i
< 20; i
++)
537 printf ("%02X", grip
[i
]);
543 rsa_key_check (struct rsa_secret_key_s
*skey
)
546 gcry_mpi_t t
= gcry_mpi_snew (0);
547 gcry_mpi_t t1
= gcry_mpi_snew (0);
548 gcry_mpi_t t2
= gcry_mpi_snew (0);
549 gcry_mpi_t phi
= gcry_mpi_snew (0);
551 /* check that n == p * q */
552 gcry_mpi_mul (t
, skey
->p
, skey
->q
);
553 if (gcry_mpi_cmp( t
, skey
->n
) )
555 log_error ("RSA oops: n != p * q\n");
559 /* check that p is less than q */
560 if (gcry_mpi_cmp (skey
->p
, skey
->q
) > 0)
564 log_info ("swapping secret primes\n");
565 tmp
= gcry_mpi_copy (skey
->p
);
566 gcry_mpi_set (skey
->p
, skey
->q
);
567 gcry_mpi_set (skey
->q
, tmp
);
568 gcry_mpi_release (tmp
);
569 /* and must recompute u of course */
570 gcry_mpi_invm (skey
->u
, skey
->p
, skey
->q
);
573 /* check that e divides neither p-1 nor q-1 */
574 gcry_mpi_sub_ui (t
, skey
->p
, 1 );
575 gcry_mpi_div (NULL
, t
, t
, skey
->e
, 0);
576 if (!gcry_mpi_cmp_ui( t
, 0) )
578 log_error ("RSA oops: e divides p-1\n");
581 gcry_mpi_sub_ui (t
, skey
->q
, 1);
582 gcry_mpi_div (NULL
, t
, t
, skey
->e
, 0);
583 if (!gcry_mpi_cmp_ui( t
, 0))
585 log_info ( "RSA oops: e divides q-1\n" );
589 /* check that d is correct. */
590 gcry_mpi_sub_ui (t1
, skey
->p
, 1);
591 gcry_mpi_sub_ui (t2
, skey
->q
, 1);
592 gcry_mpi_mul (phi
, t1
, t2
);
593 gcry_mpi_invm (t
, skey
->e
, phi
);
594 if (gcry_mpi_cmp (t
, skey
->d
))
595 { /* no: try universal exponent. */
596 gcry_mpi_gcd (t
, t1
, t2
);
597 gcry_mpi_div (t
, NULL
, phi
, t
, 0);
598 gcry_mpi_invm (t
, skey
->e
, t
);
599 if (gcry_mpi_cmp (t
, skey
->d
))
601 log_error ("RSA oops: bad secret exponent\n");
606 /* check for correctness of u */
607 gcry_mpi_invm (t
, skey
->p
, skey
->q
);
608 if (gcry_mpi_cmp (t
, skey
->u
))
610 log_info ( "RSA oops: bad u parameter\n");
615 log_info ("RSA secret key check failed\n");
617 gcry_mpi_release (t
);
618 gcry_mpi_release (t1
);
619 gcry_mpi_release (t2
);
620 gcry_mpi_release (phi
);
626 /* A callback used by p12_parse to return a certificate. */
628 import_p12_cert_cb (void *opaque
, const unsigned char *cert
, size_t certlen
)
630 struct b64state state
;
631 gpg_error_t err
, err2
;
633 err
= b64enc_start (&state
, stdout
, "CERTIFICATE");
635 err
= b64enc_write (&state
, cert
, certlen
);
636 err2
= b64enc_finish (&state
);
640 log_error ("error writing armored certificate: %s\n", gpg_strerror (err
));
644 import_p12_file (const char *fname
)
647 unsigned char *result
;
648 size_t buflen
, resultlen
, buf_off
;
652 struct rsa_secret_key_s sk
;
655 unsigned char grip
[20];
658 /* fixme: we should release some stuff on error */
660 buf
= read_file (fname
, &buflen
);
664 /* GnuPG 2.0.4 accidently created binary P12 files with the string
665 "The passphrase is %s encoded.\n\n" prepended to the ASN.1 data.
667 if (buflen
> 29 && !memcmp (buf
, "The passphrase is ", 18))
669 for (buf_off
=18; buf_off
< buflen
&& buf
[buf_off
] != '\n'; buf_off
++)
672 if (buf_off
< buflen
&& buf
[buf_off
] == '\n')
678 kparms
= p12_parse ((unsigned char*)buf
+buf_off
, buflen
-buf_off
,
679 (pw
=get_passphrase (2, 0)),
680 import_p12_cert_cb
, NULL
);
681 release_passphrase (pw
);
685 log_error ("error parsing or decrypting the PKCS-12 file\n");
688 for (i
=0; kparms
[i
]; i
++)
692 log_error ("invalid structure of private key\n");
697 /* print_mpi (" n", kparms[0]); */
698 /* print_mpi (" e", kparms[1]); */
699 /* print_mpi (" d", kparms[2]); */
700 /* print_mpi (" p", kparms[3]); */
701 /* print_mpi (" q", kparms[4]); */
702 /* print_mpi ("dmp1", kparms[5]); */
703 /* print_mpi ("dmq1", kparms[6]); */
704 /* print_mpi (" u", kparms[7]); */
712 if (rsa_key_check (&sk
))
714 /* print_mpi (" n", sk.n); */
715 /* print_mpi (" e", sk.e); */
716 /* print_mpi (" d", sk.d); */
717 /* print_mpi (" p", sk.p); */
718 /* print_mpi (" q", sk.q); */
719 /* print_mpi (" u", sk.u); */
721 /* Create an S-expresion from the parameters. */
722 rc
= gcry_sexp_build (&s_key
, NULL
,
723 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
724 sk
.n
, sk
.e
, sk
.d
, sk
.p
, sk
.q
, sk
.u
, NULL
);
725 for (i
=0; i
< 8; i
++)
726 gcry_mpi_release (kparms
[i
]);
730 log_error ("failed to created S-expression from key: %s\n",
735 /* Compute the keygrip. */
736 if (!gcry_pk_get_keygrip (s_key
, grip
))
738 log_error ("can't calculate keygrip\n");
741 log_info ("keygrip: ");
742 for (i
=0; i
< 20; i
++)
743 log_printf ("%02X", grip
[i
]);
746 /* Convert to canonical encoding. */
747 buflen
= gcry_sexp_sprint (s_key
, GCRYSEXP_FMT_CANON
, NULL
, 0);
749 key
= gcry_xmalloc_secure (buflen
);
750 buflen
= gcry_sexp_sprint (s_key
, GCRYSEXP_FMT_CANON
, key
, buflen
);
752 gcry_sexp_release (s_key
);
755 rc
= agent_protect (key
, (pw
=get_new_passphrase (4)), &result
, &resultlen
);
756 release_passphrase (pw
);
760 log_error ("protecting the key failed: %s\n", gpg_strerror (rc
));
766 char *p
= make_advanced (result
, resultlen
);
770 result
= (unsigned char*)p
;
771 resultlen
= strlen (p
);
775 store_private_key (grip
, result
, resultlen
, opt_force
);
777 fwrite (result
, resultlen
, 1, stdout
);
785 sexp_to_kparms (gcry_sexp_t sexp
)
787 gcry_sexp_t list
, l2
;
795 list
= gcry_sexp_find_token (sexp
, "private-key", 0 );
798 l2
= gcry_sexp_cadr (list
);
799 gcry_sexp_release (list
);
801 name
= gcry_sexp_nth_data (list
, 0, &n
);
802 if(!name
|| n
!= 3 || memcmp (name
, "rsa", 3))
804 gcry_sexp_release (list
);
808 /* Parameter names used with RSA. */
810 array
= xcalloc (strlen(elems
) + 1, sizeof *array
);
811 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
813 l2
= gcry_sexp_find_token (list
, s
, 1);
816 for (i
=0; i
<idx
; i
++)
817 gcry_mpi_release (array
[i
]);
819 gcry_sexp_release (list
);
820 return NULL
; /* required parameter not found */
822 array
[idx
] = gcry_sexp_nth_mpi (l2
, 1, GCRYMPI_FMT_USG
);
823 gcry_sexp_release (l2
);
826 for (i
=0; i
<idx
; i
++)
827 gcry_mpi_release (array
[i
]);
829 gcry_sexp_release (list
);
830 return NULL
; /* required parameter is invalid */
834 gcry_sexp_release (list
);
839 /* Check whether STRING is a KEYGRIP, i.e has the correct length and
840 does only consist of uppercase hex characters. */
842 is_keygrip (const char *string
)
846 for(i
=0; string
[i
] && i
< 41; i
++)
847 if (!strchr("01234567890ABCDEF", string
[i
]))
854 export_p12_file (const char *fname
)
857 gcry_mpi_t kparms
[9], *kp
;
861 struct rsa_secret_key_s sk
;
863 unsigned char *cert
= NULL
;
866 size_t keylen_for_wipe
= 0;
869 if ( is_keygrip (fname
) )
871 char hexgrip
[40+4+1];
874 assert (strlen(fname
) == 40);
875 strcpy (stpcpy (hexgrip
, fname
), ".key");
877 p
= make_filename (opt_homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
882 key
= read_key (fname
);
887 keytype
= agent_private_key_type (key
);
888 if (keytype
== PRIVATE_KEY_PROTECTED
)
890 unsigned char *tmpkey
;
893 rc
= agent_unprotect (key
, (pw
=get_passphrase (1, 0)),
894 NULL
, &tmpkey
, &tmplen
);
895 release_passphrase (pw
);
898 if (opt_status_msg
&& gpg_err_code (rc
) == GPG_ERR_BAD_PASSPHRASE
)
899 log_info ("[PROTECT-TOOL:] bad-passphrase\n");
900 log_error ("unprotecting key `%s' failed: %s\n",
901 fname
, gpg_strerror (rc
));
907 keylen_for_wipe
= tmplen
;
909 keytype
= agent_private_key_type (key
);
912 if (keytype
== PRIVATE_KEY_SHADOWED
)
914 log_error ("`%s' is a shadowed private key - can't export it\n", fname
);
915 wipememory (key
, keylen_for_wipe
);
919 else if (keytype
!= PRIVATE_KEY_CLEAR
)
921 log_error ("\%s' is not a private key\n", fname
);
922 wipememory (key
, keylen_for_wipe
);
930 cert
= (unsigned char*)read_file ("-", &certlen
);
933 wipememory (key
, keylen_for_wipe
);
940 if (gcry_sexp_new (&private, key
, 0, 0))
942 log_error ("gcry_sexp_new failed\n");
943 wipememory (key
, keylen_for_wipe
);
948 wipememory (key
, keylen_for_wipe
);
951 kp
= sexp_to_kparms (private);
952 gcry_sexp_release (private);
955 log_error ("error converting key parameters\n");
973 kparms
[5] = gcry_mpi_snew (0); /* compute d mod (p-1) */
974 gcry_mpi_sub_ui (kparms
[5], kparms
[3], 1);
975 gcry_mpi_mod (kparms
[5], sk
.d
, kparms
[5]);
976 kparms
[6] = gcry_mpi_snew (0); /* compute d mod (q-1) */
977 gcry_mpi_sub_ui (kparms
[6], kparms
[4], 1);
978 gcry_mpi_mod (kparms
[6], sk
.d
, kparms
[6]);
982 key
= p12_build (kparms
, cert
, certlen
,
983 (pw
=get_new_passphrase (3)), opt_p12_charset
, &keylen
);
984 release_passphrase (pw
);
986 for (i
=0; i
< 8; i
++)
987 gcry_mpi_release (kparms
[i
]);
991 #ifdef HAVE_DOSISH_SYSTEM
992 setmode ( fileno (stdout
) , O_BINARY
);
994 fwrite (key
, keylen
, 1, stdout
);
1000 /* Do the percent and plus/space unescaping in place and return the
1001 length of the valid buffer. */
1003 percent_plus_unescape (unsigned char *string
)
1005 unsigned char *p
= string
;
1010 if (*string
== '%' && string
[1] && string
[2])
1013 *p
++ = xtoi_2 (string
);
1017 else if (*string
== '+')
1033 /* Remove percent and plus escaping and make sure that the reuslt is a
1034 string. This is done in place. Returns STRING. */
1036 percent_plus_unescape_string (char *string
)
1038 unsigned char *p
= (unsigned char*)string
;
1041 n
= percent_plus_unescape (p
);
1049 main (int argc
, char **argv
)
1051 ARGPARSE_ARGS pargs
;
1055 set_strusage (my_strusage
);
1056 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN
);
1057 log_set_prefix ("gpg-protect-tool", 1);
1059 /* Make sure that our subsystems are ready. */
1060 init_common_subsystems ();
1064 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION
) )
1066 log_fatal( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
1067 NEED_LIBGCRYPT_VERSION
, gcry_check_version (NULL
) );
1070 setup_libgcrypt_logging ();
1071 gcry_control (GCRYCTL_INIT_SECMEM
, 16384, 0);
1074 opt_homedir
= default_homedir ();
1079 pargs
.flags
= 1; /* (do not remove the args) */
1080 while (arg_parse (&pargs
, opts
) )
1082 switch (pargs
.r_opt
)
1084 case oVerbose
: opt
.verbose
++; break;
1085 case oArmor
: opt_armor
=1; break;
1086 case oCanonical
: opt_canonical
=1; break;
1087 case oHomedir
: opt_homedir
= pargs
.r
.ret_str
; break;
1089 case oProtect
: cmd
= oProtect
; break;
1090 case oUnprotect
: cmd
= oUnprotect
; break;
1091 case oShadow
: cmd
= oShadow
; break;
1092 case oShowShadowInfo
: cmd
= oShowShadowInfo
; break;
1093 case oShowKeygrip
: cmd
= oShowKeygrip
; break;
1094 case oP12Import
: cmd
= oP12Import
; break;
1095 case oP12Export
: cmd
= oP12Export
; break;
1096 case oP12Charset
: opt_p12_charset
= pargs
.r
.ret_str
; break;
1098 case oPassphrase
: opt_passphrase
= pargs
.r
.ret_str
; break;
1099 case oStore
: opt_store
= 1; break;
1100 case oForce
: opt_force
= 1; break;
1101 case oNoFailOnExist
: opt_no_fail_on_exist
= 1; break;
1102 case oHaveCert
: opt_have_cert
= 1; break;
1103 case oPrompt
: opt_prompt
= pargs
.r
.ret_str
; break;
1104 case oStatusMsg
: opt_status_msg
= 1; break;
1106 default : pargs
.err
= 2; break;
1109 if (log_get_errorcount(0))
1118 /* Tell simple-pwquery about the the standard socket name. */
1120 char *tmp
= make_filename (opt_homedir
, "S.gpg-agent", NULL
);
1121 simple_pw_set_socket (tmp
);
1126 opt_prompt
= percent_plus_unescape_string (xstrdup (opt_prompt
));
1128 if (cmd
== oProtect
)
1129 read_and_protect (fname
);
1130 else if (cmd
== oUnprotect
)
1131 read_and_unprotect (fname
);
1132 else if (cmd
== oShadow
)
1133 read_and_shadow (fname
);
1134 else if (cmd
== oShowShadowInfo
)
1135 show_shadow_info (fname
);
1136 else if (cmd
== oShowKeygrip
)
1137 show_keygrip (fname
);
1138 else if (cmd
== oP12Import
)
1139 import_p12_file (fname
);
1140 else if (cmd
== oP12Export
)
1141 export_p12_file (fname
);
1146 return 8; /*NOTREACHED*/
1152 rc
= rc
? rc
: log_get_errorcount(0)? 2 : 0;
1157 /* Return the passphrase string and ask the agent if it has not been
1158 set from the command line PROMPTNO select the prompt to display:
1160 1 = taken from the option --prompt
1161 2 = for unprotecting a pkcs#12 object
1162 3 = for protecting a new pkcs#12 object
1163 4 = for protecting an imported pkcs#12 in our system
1164 5 = reenter the passphrase
1165 When adding 100 to the values, a "does not match - try again" error
1169 get_passphrase (int promptno
, int opt_check
)
1178 return xstrdup (opt_passphrase
);
1180 error_msgno
= promptno
/ 100;
1183 orig_codeset
= i18n_switchto_utf8 ();
1185 if (promptno
== 1 && opt_prompt
)
1187 else if (promptno
== 2)
1188 desc
= _("Please enter the passphrase to unprotect the "
1190 else if (promptno
== 3)
1191 desc
= _("Please enter the passphrase to protect the "
1192 "new PKCS#12 object.");
1193 else if (promptno
== 4)
1194 desc
= _("Please enter the passphrase to protect the "
1195 "imported object within the GnuPG system.");
1196 else if (promptno
== 5)
1197 desc
= _("Please re-enter this passphrase");
1199 desc
= _("Please enter the passphrase or the PIN\n"
1200 "needed to complete this operation.");
1202 pw
= simple_pwquery (NULL
,
1203 error_msgno
== 1? _("does not match - try again"):NULL
,
1204 _("Passphrase:"), desc
, opt_check
, &err
);
1205 err
= map_spwq_error (err
);
1207 i18n_switchback (orig_codeset
);
1212 log_error (_("error while asking for the passphrase: %s\n"),
1213 gpg_strerror (err
));
1215 log_info (_("cancelled\n"));
1223 /* Same as get_passphrase but requests it a second time and compares
1224 it to the one entered the first time. */
1226 get_new_passphrase (int promptno
)
1229 int i
, secondpromptno
;
1231 pw
= get_passphrase (promptno
, 1);
1233 return NULL
; /* Canceled. */
1235 return pw
; /* Empty passphrase - no need to ask for repeating it. */
1238 for (i
=0; i
< 3; i
++)
1240 char *pw2
= get_passphrase (secondpromptno
, 0);
1244 return NULL
; /* Canceled. */
1246 if (!strcmp (pw
, pw2
))
1249 return pw
; /* Okay. */
1251 secondpromptno
= 105;
1255 return NULL
; /* 3 times repeated wrong - cancel. */
1261 release_passphrase (char *pw
)
1265 wipememory (pw
, strlen (pw
));
1271 store_private_key (const unsigned char *grip
,
1272 const void *buffer
, size_t length
, int force
)
1277 char hexgrip
[40+4+1];
1279 for (i
=0; i
< 20; i
++)
1280 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
1281 strcpy (hexgrip
+40, ".key");
1283 fname
= make_filename (opt_homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
1285 fp
= fopen (fname
, "wb");
1288 if (!access (fname
, F_OK
))
1291 log_info ("[PROTECT-TOOL:] secretkey-exists\n");
1292 if (opt_no_fail_on_exist
)
1293 log_info ("secret key file `%s' already exists\n", fname
);
1295 log_error ("secret key file `%s' already exists\n", fname
);
1297 return opt_no_fail_on_exist
? 0 : -1;
1299 fp
= fopen (fname
, "wbx"); /* FIXME: the x is a GNU extension - let
1300 configure check whether this actually
1306 log_error ("can't create `%s': %s\n", fname
, strerror (errno
));
1311 if (fwrite (buffer
, length
, 1, fp
) != 1)
1313 log_error ("error writing `%s': %s\n", fname
, strerror (errno
));
1321 log_error ("error closing `%s': %s\n", fname
, strerror (errno
));
1326 log_info ("secret key stored as `%s'\n", fname
);
1329 log_info ("[PROTECT-TOOL:] secretkey-stored\n");