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
;
635 err
= b64enc_start (&state
, stdout
, "CERTIFICATE");
637 err
= b64enc_write (&state
, cert
, certlen
);
638 err2
= b64enc_finish (&state
);
642 log_error ("error writing armored certificate: %s\n", gpg_strerror (err
));
646 import_p12_file (const char *fname
)
649 unsigned char *result
;
650 size_t buflen
, resultlen
, buf_off
;
654 struct rsa_secret_key_s sk
;
657 unsigned char grip
[20];
660 /* fixme: we should release some stuff on error */
662 buf
= read_file (fname
, &buflen
);
666 /* GnuPG 2.0.4 accidently created binary P12 files with the string
667 "The passphrase is %s encoded.\n\n" prepended to the ASN.1 data.
669 if (buflen
> 29 && !memcmp (buf
, "The passphrase is ", 18))
671 for (buf_off
=18; buf_off
< buflen
&& buf
[buf_off
] != '\n'; buf_off
++)
674 if (buf_off
< buflen
&& buf
[buf_off
] == '\n')
680 kparms
= p12_parse ((unsigned char*)buf
+buf_off
, buflen
-buf_off
,
681 (pw
=get_passphrase (2, 0)),
682 import_p12_cert_cb
, NULL
);
683 release_passphrase (pw
);
687 log_error ("error parsing or decrypting the PKCS-12 file\n");
690 for (i
=0; kparms
[i
]; i
++)
694 log_error ("invalid structure of private key\n");
699 /* print_mpi (" n", kparms[0]); */
700 /* print_mpi (" e", kparms[1]); */
701 /* print_mpi (" d", kparms[2]); */
702 /* print_mpi (" p", kparms[3]); */
703 /* print_mpi (" q", kparms[4]); */
704 /* print_mpi ("dmp1", kparms[5]); */
705 /* print_mpi ("dmq1", kparms[6]); */
706 /* print_mpi (" u", kparms[7]); */
714 if (rsa_key_check (&sk
))
716 /* print_mpi (" n", sk.n); */
717 /* print_mpi (" e", sk.e); */
718 /* print_mpi (" d", sk.d); */
719 /* print_mpi (" p", sk.p); */
720 /* print_mpi (" q", sk.q); */
721 /* print_mpi (" u", sk.u); */
723 /* Create an S-expresion from the parameters. */
724 rc
= gcry_sexp_build (&s_key
, NULL
,
725 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
726 sk
.n
, sk
.e
, sk
.d
, sk
.p
, sk
.q
, sk
.u
, NULL
);
727 for (i
=0; i
< 8; i
++)
728 gcry_mpi_release (kparms
[i
]);
732 log_error ("failed to created S-expression from key: %s\n",
737 /* Compute the keygrip. */
738 if (!gcry_pk_get_keygrip (s_key
, grip
))
740 log_error ("can't calculate keygrip\n");
743 log_info ("keygrip: ");
744 for (i
=0; i
< 20; i
++)
745 log_printf ("%02X", grip
[i
]);
748 /* Convert to canonical encoding. */
749 buflen
= gcry_sexp_sprint (s_key
, GCRYSEXP_FMT_CANON
, NULL
, 0);
751 key
= gcry_xmalloc_secure (buflen
);
752 buflen
= gcry_sexp_sprint (s_key
, GCRYSEXP_FMT_CANON
, key
, buflen
);
754 gcry_sexp_release (s_key
);
757 pw
= get_new_passphrase (4);
759 rc
= gpg_error (GPG_ERR_CANCELED
);
761 rc
= agent_protect (key
, pw
, &result
, &resultlen
);
762 release_passphrase (pw
);
766 log_error ("protecting the key failed: %s\n", gpg_strerror (rc
));
772 char *p
= make_advanced (result
, resultlen
);
776 result
= (unsigned char*)p
;
777 resultlen
= strlen (p
);
781 store_private_key (grip
, result
, resultlen
, opt_force
);
783 fwrite (result
, resultlen
, 1, stdout
);
791 sexp_to_kparms (gcry_sexp_t sexp
)
793 gcry_sexp_t list
, l2
;
801 list
= gcry_sexp_find_token (sexp
, "private-key", 0 );
804 l2
= gcry_sexp_cadr (list
);
805 gcry_sexp_release (list
);
807 name
= gcry_sexp_nth_data (list
, 0, &n
);
808 if(!name
|| n
!= 3 || memcmp (name
, "rsa", 3))
810 gcry_sexp_release (list
);
814 /* Parameter names used with RSA. */
816 array
= xcalloc (strlen(elems
) + 1, sizeof *array
);
817 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
819 l2
= gcry_sexp_find_token (list
, s
, 1);
822 for (i
=0; i
<idx
; i
++)
823 gcry_mpi_release (array
[i
]);
825 gcry_sexp_release (list
);
826 return NULL
; /* required parameter not found */
828 array
[idx
] = gcry_sexp_nth_mpi (l2
, 1, GCRYMPI_FMT_USG
);
829 gcry_sexp_release (l2
);
832 for (i
=0; i
<idx
; i
++)
833 gcry_mpi_release (array
[i
]);
835 gcry_sexp_release (list
);
836 return NULL
; /* required parameter is invalid */
840 gcry_sexp_release (list
);
845 /* Check whether STRING is a KEYGRIP, i.e has the correct length and
846 does only consist of uppercase hex characters. */
848 is_keygrip (const char *string
)
852 for(i
=0; string
[i
] && i
< 41; i
++)
853 if (!strchr("01234567890ABCDEF", string
[i
]))
860 export_p12_file (const char *fname
)
863 gcry_mpi_t kparms
[9], *kp
;
867 struct rsa_secret_key_s sk
;
869 unsigned char *cert
= NULL
;
872 size_t keylen_for_wipe
= 0;
875 if ( is_keygrip (fname
) )
877 char hexgrip
[40+4+1];
880 assert (strlen(fname
) == 40);
881 strcpy (stpcpy (hexgrip
, fname
), ".key");
883 p
= make_filename (opt_homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
888 key
= read_key (fname
);
893 keytype
= agent_private_key_type (key
);
894 if (keytype
== PRIVATE_KEY_PROTECTED
)
896 unsigned char *tmpkey
;
899 rc
= agent_unprotect (key
, (pw
=get_passphrase (1, 0)),
900 NULL
, &tmpkey
, &tmplen
);
901 release_passphrase (pw
);
904 if (opt_status_msg
&& gpg_err_code (rc
) == GPG_ERR_BAD_PASSPHRASE
)
905 log_info ("[PROTECT-TOOL:] bad-passphrase\n");
906 log_error ("unprotecting key `%s' failed: %s\n",
907 fname
, gpg_strerror (rc
));
913 keylen_for_wipe
= tmplen
;
915 keytype
= agent_private_key_type (key
);
918 if (keytype
== PRIVATE_KEY_SHADOWED
)
920 log_error ("`%s' is a shadowed private key - can't export it\n", fname
);
921 wipememory (key
, keylen_for_wipe
);
925 else if (keytype
!= PRIVATE_KEY_CLEAR
)
927 log_error ("\%s' is not a private key\n", fname
);
928 wipememory (key
, keylen_for_wipe
);
936 cert
= (unsigned char*)read_file ("-", &certlen
);
939 wipememory (key
, keylen_for_wipe
);
946 if (gcry_sexp_new (&private, key
, 0, 0))
948 log_error ("gcry_sexp_new failed\n");
949 wipememory (key
, keylen_for_wipe
);
954 wipememory (key
, keylen_for_wipe
);
957 kp
= sexp_to_kparms (private);
958 gcry_sexp_release (private);
961 log_error ("error converting key parameters\n");
979 kparms
[5] = gcry_mpi_snew (0); /* compute d mod (p-1) */
980 gcry_mpi_sub_ui (kparms
[5], kparms
[3], 1);
981 gcry_mpi_mod (kparms
[5], sk
.d
, kparms
[5]);
982 kparms
[6] = gcry_mpi_snew (0); /* compute d mod (q-1) */
983 gcry_mpi_sub_ui (kparms
[6], kparms
[4], 1);
984 gcry_mpi_mod (kparms
[6], sk
.d
, kparms
[6]);
988 pw
= get_new_passphrase (3);
992 key
= p12_build (kparms
, cert
, certlen
, pw
, opt_p12_charset
, &keylen
);
993 release_passphrase (pw
);
995 for (i
=0; i
< 8; i
++)
996 gcry_mpi_release (kparms
[i
]);
1000 #ifdef HAVE_DOSISH_SYSTEM
1001 setmode ( fileno (stdout
) , O_BINARY
);
1003 fwrite (key
, keylen
, 1, stdout
);
1009 /* Do the percent and plus/space unescaping in place and return the
1010 length of the valid buffer. */
1012 percent_plus_unescape (unsigned char *string
)
1014 unsigned char *p
= string
;
1019 if (*string
== '%' && string
[1] && string
[2])
1022 *p
++ = xtoi_2 (string
);
1026 else if (*string
== '+')
1042 /* Remove percent and plus escaping and make sure that the reuslt is a
1043 string. This is done in place. Returns STRING. */
1045 percent_plus_unescape_string (char *string
)
1047 unsigned char *p
= (unsigned char*)string
;
1050 n
= percent_plus_unescape (p
);
1058 main (int argc
, char **argv
)
1060 ARGPARSE_ARGS pargs
;
1064 set_strusage (my_strusage
);
1065 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN
);
1066 log_set_prefix ("gpg-protect-tool", 1);
1068 /* Make sure that our subsystems are ready. */
1070 init_common_subsystems ();
1072 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION
) )
1074 log_fatal( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
1075 NEED_LIBGCRYPT_VERSION
, gcry_check_version (NULL
) );
1078 setup_libgcrypt_logging ();
1079 gcry_control (GCRYCTL_INIT_SECMEM
, 16384, 0);
1082 opt_homedir
= default_homedir ();
1087 pargs
.flags
= 1; /* (do not remove the args) */
1088 while (arg_parse (&pargs
, opts
) )
1090 switch (pargs
.r_opt
)
1092 case oVerbose
: opt
.verbose
++; break;
1093 case oArmor
: opt_armor
=1; break;
1094 case oCanonical
: opt_canonical
=1; break;
1095 case oHomedir
: opt_homedir
= pargs
.r
.ret_str
; break;
1097 case oProtect
: cmd
= oProtect
; break;
1098 case oUnprotect
: cmd
= oUnprotect
; break;
1099 case oShadow
: cmd
= oShadow
; break;
1100 case oShowShadowInfo
: cmd
= oShowShadowInfo
; break;
1101 case oShowKeygrip
: cmd
= oShowKeygrip
; break;
1102 case oP12Import
: cmd
= oP12Import
; break;
1103 case oP12Export
: cmd
= oP12Export
; break;
1104 case oP12Charset
: opt_p12_charset
= pargs
.r
.ret_str
; break;
1106 case oPassphrase
: opt_passphrase
= pargs
.r
.ret_str
; break;
1107 case oStore
: opt_store
= 1; break;
1108 case oForce
: opt_force
= 1; break;
1109 case oNoFailOnExist
: opt_no_fail_on_exist
= 1; break;
1110 case oHaveCert
: opt_have_cert
= 1; break;
1111 case oPrompt
: opt_prompt
= pargs
.r
.ret_str
; break;
1112 case oStatusMsg
: opt_status_msg
= 1; break;
1114 default : pargs
.err
= 2; break;
1117 if (log_get_errorcount(0))
1126 /* Tell simple-pwquery about the the standard socket name. */
1128 char *tmp
= make_filename (opt_homedir
, "S.gpg-agent", NULL
);
1129 simple_pw_set_socket (tmp
);
1134 opt_prompt
= percent_plus_unescape_string (xstrdup (opt_prompt
));
1136 if (cmd
== oProtect
)
1137 read_and_protect (fname
);
1138 else if (cmd
== oUnprotect
)
1139 read_and_unprotect (fname
);
1140 else if (cmd
== oShadow
)
1141 read_and_shadow (fname
);
1142 else if (cmd
== oShowShadowInfo
)
1143 show_shadow_info (fname
);
1144 else if (cmd
== oShowKeygrip
)
1145 show_keygrip (fname
);
1146 else if (cmd
== oP12Import
)
1147 import_p12_file (fname
);
1148 else if (cmd
== oP12Export
)
1149 export_p12_file (fname
);
1154 return 8; /*NOTREACHED*/
1160 rc
= rc
? rc
: log_get_errorcount(0)? 2 : 0;
1165 /* Return the passphrase string and ask the agent if it has not been
1166 set from the command line PROMPTNO select the prompt to display:
1168 1 = taken from the option --prompt
1169 2 = for unprotecting a pkcs#12 object
1170 3 = for protecting a new pkcs#12 object
1171 4 = for protecting an imported pkcs#12 in our system
1172 5 = reenter the passphrase
1173 When adding 100 to the values, a "does not match - try again" error
1177 get_passphrase (int promptno
, int opt_check
)
1186 return xstrdup (opt_passphrase
);
1188 error_msgno
= promptno
/ 100;
1191 orig_codeset
= i18n_switchto_utf8 ();
1193 if (promptno
== 1 && opt_prompt
)
1195 else if (promptno
== 2)
1196 desc
= _("Please enter the passphrase to unprotect the "
1198 else if (promptno
== 3)
1199 desc
= _("Please enter the passphrase to protect the "
1200 "new PKCS#12 object.");
1201 else if (promptno
== 4)
1202 desc
= _("Please enter the passphrase to protect the "
1203 "imported object within the GnuPG system.");
1204 else if (promptno
== 5)
1205 desc
= _("Please re-enter this passphrase");
1207 desc
= _("Please enter the passphrase or the PIN\n"
1208 "needed to complete this operation.");
1210 pw
= simple_pwquery (NULL
,
1211 error_msgno
== 1? _("does not match - try again"):NULL
,
1212 _("Passphrase:"), desc
, opt_check
, &err
);
1213 err
= map_spwq_error (err
);
1215 i18n_switchback (orig_codeset
);
1220 log_error (_("error while asking for the passphrase: %s\n"),
1221 gpg_strerror (err
));
1223 log_info (_("cancelled\n"));
1231 /* Same as get_passphrase but requests it a second time and compares
1232 it to the one entered the first time. */
1234 get_new_passphrase (int promptno
)
1237 int i
, secondpromptno
;
1239 pw
= get_passphrase (promptno
, 1);
1241 return NULL
; /* Canceled. */
1243 return pw
; /* Empty passphrase - no need to ask for repeating it. */
1246 for (i
=0; i
< 3; i
++)
1248 char *pw2
= get_passphrase (secondpromptno
, 0);
1252 return NULL
; /* Canceled. */
1254 if (!strcmp (pw
, pw2
))
1257 return pw
; /* Okay. */
1259 secondpromptno
= 105;
1263 return NULL
; /* 3 times repeated wrong - cancel. */
1269 release_passphrase (char *pw
)
1273 wipememory (pw
, strlen (pw
));
1279 store_private_key (const unsigned char *grip
,
1280 const void *buffer
, size_t length
, int force
)
1285 char hexgrip
[40+4+1];
1287 for (i
=0; i
< 20; i
++)
1288 sprintf (hexgrip
+2*i
, "%02X", grip
[i
]);
1289 strcpy (hexgrip
+40, ".key");
1291 fname
= make_filename (opt_homedir
, GNUPG_PRIVATE_KEYS_DIR
, hexgrip
, NULL
);
1293 fp
= fopen (fname
, "wb");
1296 if (!access (fname
, F_OK
))
1299 log_info ("[PROTECT-TOOL:] secretkey-exists\n");
1300 if (opt_no_fail_on_exist
)
1301 log_info ("secret key file `%s' already exists\n", fname
);
1303 log_error ("secret key file `%s' already exists\n", fname
);
1305 return opt_no_fail_on_exist
? 0 : -1;
1307 fp
= fopen (fname
, "wbx"); /* FIXME: the x is a GNU extension - let
1308 configure check whether this actually
1314 log_error ("can't create `%s': %s\n", fname
, strerror (errno
));
1319 if (fwrite (buffer
, length
, 1, fp
) != 1)
1321 log_error ("error writing `%s': %s\n", fname
, strerror (errno
));
1329 log_error ("error closing `%s': %s\n", fname
, strerror (errno
));
1334 log_info ("secret key stored as `%s'\n", fname
);
1337 log_info ("[PROTECT-TOOL:] secretkey-stored\n");