1
1
/* protect-tool.c - A tool to test the secret key protection
2
* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2
* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
4
4
* This file is part of GnuPG.
6
6
* GnuPG is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
8
* the Free Software Foundation; either version 3 of the License, or
9
9
* (at your option) any later version.
11
11
* GnuPG is distributed in the hope that it will be useful,
14
14
* GNU General Public License for more details.
16
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
17
* along with this program; if not, see <http://www.gnu.org/licenses/>.
21
20
#include <config.h>
95
95
static const char *opt_passphrase;
96
96
static char *opt_prompt;
97
97
static int opt_status_msg;
98
static const char *opt_p12_charset;
99
static char *get_passphrase (int promptno);
100
static char *get_passphrase (int promptno, int opt_check);
100
101
static char *get_new_passphrase (int promptno);
101
102
static void release_passphrase (char *pw);
102
103
static int store_private_key (const unsigned char *grip,
117
118
{ oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
118
119
{ oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""},
120
{ oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"},
121
{ oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"},
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" },
122
125
{ oHaveCert, "have-cert", 0, "certificate to export provided on STDIN"},
123
126
{ oStore, "store", 0, "store the created key in the appropriate place"},
124
127
{ oForce, "force", 0, "force overwriting"},
126
129
{ oHomedir, "homedir", 2, "@" },
127
130
{ oPrompt, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"},
128
131
{ oStatusMsg, "enable-status-msg", 0, "@"},
145
149
case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n");
147
case 41: p = _("Syntax: gpg-protect-tool [options] [args]]\n"
151
case 41: p = _("Syntax: gpg-protect-tool [options] [args]\n"
148
152
"Secret key maintenance tool\n");
161
#ifdef USE_SIMPLE_GETTEXT
162
set_gettext_file( PACKAGE_GT );
165
setlocale (LC_ALL, "");
166
bindtextdomain (PACKAGE_GT, LOCALEDIR);
167
textdomain (PACKAGE_GT);
174
/* Used by gcry for logging */
176
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
178
/* translate the log levels */
181
case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
182
case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
183
case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
184
case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
185
case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
186
case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
187
case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
188
default: level = JNLIB_LOG_ERROR; break; }
189
log_logv (level, fmt, arg_ptr);
161
/* Include the implementation of map_spwq_error. */
193
164
/* static void */
194
165
/* print_mpi (const char *text, gcry_mpi_t a) */
395
366
unsigned char *result;
396
367
size_t resultlen;
369
gnupg_isotime_t protected_at;
399
371
key = read_key (fname);
403
rc = agent_unprotect (key, (pw=get_passphrase (1)), &result, &resultlen);
375
rc = agent_unprotect (key, (pw=get_passphrase (1, 0)),
376
protected_at, &result, &resultlen);
404
377
release_passphrase (pw);
410
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);
416
394
char *p = make_advanced (result, resultlen);
686
kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2)),
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)),
687
680
import_p12_cert_cb, NULL);
688
681
release_passphrase (pw);
897
890
unsigned char *tmpkey;
900
rc = agent_unprotect (key, (pw=get_passphrase (1)), &tmpkey, &tmplen);
893
rc = agent_unprotect (key, (pw=get_passphrase (1, 0)),
894
NULL, &tmpkey, &tmplen);
901
895
release_passphrase (pw);
986
980
kparms[8] = NULL;
988
982
key = p12_build (kparms, cert, certlen,
989
(pw=get_new_passphrase (3)), &keylen);
983
(pw=get_new_passphrase (3)), opt_p12_charset, &keylen);
990
984
release_passphrase (pw);
992
986
for (i=0; i < 8; i++)
1062
1056
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
1063
1057
log_set_prefix ("gpg-protect-tool", 1);
1065
/* Try to auto set the character set. */
1066
set_native_charset (NULL);
1059
/* Make sure that our subsystems are ready. */
1060
init_common_subsystems ();
1070
1064
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
1072
log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
1066
log_fatal( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
1073
1067
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
1076
gcry_set_log_handler (my_gcry_logger, NULL);
1070
setup_libgcrypt_logging ();
1078
1071
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1100
1093
case oShowKeygrip: cmd = oShowKeygrip; break;
1101
1094
case oP12Import: cmd = oP12Import; break;
1102
1095
case oP12Export: cmd = oP12Export; break;
1096
case oP12Charset: opt_p12_charset = pargs.r.ret_str; break;
1104
1098
case oPassphrase: opt_passphrase = pargs.r.ret_str; break;
1105
1099
case oStore: opt_store = 1; break;
1121
1115
else if (argc > 1)
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);
1124
1125
if (opt_prompt)
1125
1126
opt_prompt = percent_plus_unescape_string (xstrdup (opt_prompt));
1161
1162
3 = for protecting a new pkcs#12 object
1162
1163
4 = for protecting an imported pkcs#12 in our system
1163
1164
5 = reenter the passphrase
1164
When adding 100 to the values, a "does not match - try again" errro message is shown.
1165
When adding 100 to the values, a "does not match - try again" error
1167
get_passphrase (int promptno)
1169
get_passphrase (int promptno, int opt_check)
1171
1173
const char *desc;
1172
#ifdef HAVE_LANGINFO_CODESET
1173
char *orig_codeset = NULL;
1175
1175
int error_msgno;
1178
1177
if (opt_passphrase)
1179
1178
return xstrdup (opt_passphrase);
1181
1180
error_msgno = promptno / 100;
1182
1181
promptno %= 100;
1185
/* The Assuan agent protocol requires us to transmit utf-8 strings */
1186
orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL);
1187
#ifdef HAVE_LANGINFO_CODESET
1189
orig_codeset = nl_langinfo (CODESET);
1191
if (orig_codeset && !strcmp (orig_codeset, "UTF-8"))
1192
orig_codeset = NULL;
1195
/* We only switch when we are able to restore the codeset later. */
1196
orig_codeset = xstrdup (orig_codeset);
1197
if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8"))
1198
orig_codeset = NULL;
1183
orig_codeset = i18n_switchto_utf8 ();
1202
1185
if (promptno == 1 && opt_prompt)
1203
1186
desc = opt_prompt;
1219
1202
pw = simple_pwquery (NULL,
1220
1203
error_msgno == 1? _("does not match - try again"):NULL,
1221
_("Passphrase:"), desc, &err);
1204
_("Passphrase:"), desc, opt_check, &err);
1205
err = map_spwq_error (err);
1226
bind_textdomain_codeset (PACKAGE_GT, orig_codeset);
1227
xfree (orig_codeset);
1207
i18n_switchback (orig_codeset);
1251
1229
int i, secondpromptno;
1253
pw = get_passphrase (promptno);
1231
pw = get_passphrase (promptno, 1);
1255
1233
return NULL; /* Canceled. */
1257
return pw; /* Empty passphrase - no need to as for repeating it. */
1235
return pw; /* Empty passphrase - no need to ask for repeating it. */
1259
1237
secondpromptno = 5;
1260
1238
for (i=0; i < 3; i++)
1262
char *pw2 = get_passphrase (secondpromptno);
1240
char *pw2 = get_passphrase (secondpromptno, 0);