1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-05-31 22:18:03 +02:00

Allow setting of the passphrase encoding of pkcs#12 files.

New option --p12-charset.
This commit is contained in:
Werner Koch 2007-03-20 10:00:55 +00:00
parent 083010a53d
commit fd628ffda1
10 changed files with 130 additions and 18 deletions

2
NEWS
View File

@ -5,7 +5,7 @@ Noteworthy changes in version 2.0.4
without the funopen/fopencookie API. without the funopen/fopencookie API.
* PKCS#12 import now tries several encodings in case the passphrase * PKCS#12 import now tries several encodings in case the passphrase
was not utf-8 encoded. was not utf-8 encoded. New option --p12-charset for gpgsm.
Noteworthy changes in version 2.0.3 (2007-03-08) Noteworthy changes in version 2.0.3 (2007-03-08)

View File

@ -1,3 +1,8 @@
2007-03-20 Werner Koch <wk@g10code.com>
* protect-tool.c: New option --p12-charset.
* minip12.c (p12_build): Implement it.
2007-03-19 Werner Koch <wk@g10code.com> 2007-03-19 Werner Koch <wk@g10code.com>
* minip12.c: Include iconv.h. * minip12.c: Include iconv.h.

View File

@ -28,11 +28,11 @@
#include <assert.h> #include <assert.h>
#include <gcrypt.h> #include <gcrypt.h>
#include <iconv.h> #include <iconv.h>
#include <errno.h>
#ifdef TEST #ifdef TEST
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#endif #endif
#include "../jnlib/logging.h" #include "../jnlib/logging.h"
@ -518,6 +518,10 @@ decrypt_block (const void *ciphertext, unsigned char *plaintext, size_t length,
"ISO-8859-8", "ISO-8859-8",
"ISO-8859-9", "ISO-8859-9",
"KOI8-R", "KOI8-R",
"IBM437",
"IBM850",
"EUC-JP",
"BIG5",
NULL NULL
}; };
int charsetidx = 0; int charsetidx = 0;
@ -2139,25 +2143,75 @@ build_cert_sequence (unsigned char *buffer, size_t buflen,
} }
/* Expect the RSA key parameters in KPARMS and a password in /* Expect the RSA key parameters in KPARMS and a password in PW.
PW. Create a PKCS structure from it and return it as well as the Create a PKCS structure from it and return it as well as the length
length in R_LENGTH; return NULL in case of an error. */ in R_LENGTH; return NULL in case of an error. If CHARSET is not
NULL, re-encode PW to that character set. */
unsigned char * unsigned char *
p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen,
const char *pw, size_t *r_length) const char *pw, const char *charset, size_t *r_length)
{ {
unsigned char *buffer; unsigned char *buffer = NULL;
size_t n, buflen; size_t n, buflen;
char salt[8]; char salt[8];
struct buffer_s seqlist[3]; struct buffer_s seqlist[3];
int seqlistidx = 0; int seqlistidx = 0;
unsigned char sha1hash[20]; unsigned char sha1hash[20];
char keyidstr[8+1]; char keyidstr[8+1];
char *pwbuf = NULL;
size_t pwbufsize = 0;
n = buflen = 0; /* (avoid compiler warning). */ n = buflen = 0; /* (avoid compiler warning). */
memset (sha1hash, 0, 20); memset (sha1hash, 0, 20);
*keyidstr = 0; *keyidstr = 0;
if (charset && pw && *pw)
{
iconv_t cd;
const char *inptr;
char *outptr;
size_t inbytes, outbytes;
/* We assume that the converted passphrase is at max 2 times
longer than its utf-8 encoding. */
pwbufsize = strlen (pw)*2 + 1;
pwbuf = gcry_malloc_secure (pwbufsize);
if (!pwbuf)
{
log_error ("out of secure memory while converting passphrase\n");
goto failure;
}
cd = iconv_open (charset, "utf-8");
if (cd == (iconv_t)(-1))
{
log_error ("can't convert passphrase to"
" requested charset `%s': %s\n",
charset, strerror (errno));
gcry_free (pwbuf);
goto failure;
}
inptr = pw;
inbytes = strlen (pw);
outptr = pwbuf;
outbytes = pwbufsize - 1;
if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
&outptr, &outbytes) == (size_t)-1)
{
log_error ("error converting passphrase to"
" requested charset `%s': %s\n",
charset, strerror (errno));
gcry_free (pwbuf);
iconv_close (cd);
goto failure;
}
*outptr = 0;
iconv_close (cd);
pw = pwbuf;
}
if (cert && certlen) if (cert && certlen)
{ {
/* Calculate the hash value we need for the bag attributes. */ /* Calculate the hash value we need for the bag attributes. */
@ -2219,6 +2273,11 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen,
buffer = create_final (seqlist, pw, &buflen); buffer = create_final (seqlist, pw, &buflen);
failure: failure:
if (pwbuf)
{
wipememory (pwbuf, pwbufsize);
gcry_free (pwbuf);
}
for ( ; seqlistidx; seqlistidx--) for ( ; seqlistidx; seqlistidx--)
gcry_free (seqlist[seqlistidx].buffer); gcry_free (seqlist[seqlistidx].buffer);

View File

@ -31,7 +31,8 @@ gcry_mpi_t *p12_parse (const unsigned char *buffer, size_t length,
unsigned char *p12_build (gcry_mpi_t *kparms, unsigned char *p12_build (gcry_mpi_t *kparms,
unsigned char *cert, size_t certlen, unsigned char *cert, size_t certlen,
const char *pw, size_t *r_length); const char *pw, const char *charset,
size_t *r_length);
#endif /*MINIP12_H*/ #endif /*MINIP12_H*/

View File

@ -65,6 +65,7 @@ enum cmd_and_opt_values
oP12Import, oP12Import,
oP12Export, oP12Export,
oP12Charset,
oStore, oStore,
oForce, oForce,
oHaveCert, oHaveCert,
@ -96,6 +97,7 @@ static int opt_have_cert;
static const char *opt_passphrase; static const char *opt_passphrase;
static char *opt_prompt; static char *opt_prompt;
static int opt_status_msg; static int opt_status_msg;
static const char *opt_p12_charset;
static char *get_passphrase (int promptno, int opt_check); static char *get_passphrase (int promptno, int opt_check);
static char *get_new_passphrase (int promptno); static char *get_new_passphrase (int promptno);
@ -118,8 +120,10 @@ static ARGPARSE_OPTS opts[] = {
{ oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"}, { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
{ oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""}, { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""},
{ oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"}, { oP12Import, "p12-import", 256, "import a pkcs#12 encoded private key"},
{ oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"}, { oP12Export, "p12-export", 256, "export a private key pkcs#12 encoded"},
{ oP12Charset,"p12-charset", 2,
"|NAME|set charset for a new PKCS#12 passphrase to NAME" },
{ oHaveCert, "have-cert", 0, "certificate to export provided on STDIN"}, { oHaveCert, "have-cert", 0, "certificate to export provided on STDIN"},
{ oStore, "store", 0, "store the created key in the appropriate place"}, { oStore, "store", 0, "store the created key in the appropriate place"},
{ oForce, "force", 0, "force overwriting"}, { oForce, "force", 0, "force overwriting"},
@ -127,6 +131,7 @@ static ARGPARSE_OPTS opts[] = {
{ oHomedir, "homedir", 2, "@" }, { oHomedir, "homedir", 2, "@" },
{ oPrompt, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"}, { oPrompt, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"},
{ oStatusMsg, "enable-status-msg", 0, "@"}, { oStatusMsg, "enable-status-msg", 0, "@"},
{0} {0}
}; };
@ -987,7 +992,7 @@ export_p12_file (const char *fname)
kparms[8] = NULL; kparms[8] = NULL;
key = p12_build (kparms, cert, certlen, key = p12_build (kparms, cert, certlen,
(pw=get_new_passphrase (3)), &keylen); (pw=get_new_passphrase (3)), opt_p12_charset, &keylen);
release_passphrase (pw); release_passphrase (pw);
xfree (cert); xfree (cert);
for (i=0; i < 8; i++) for (i=0; i < 8; i++)
@ -1101,6 +1106,7 @@ main (int argc, char **argv )
case oShowKeygrip: cmd = oShowKeygrip; break; case oShowKeygrip: cmd = oShowKeygrip; break;
case oP12Import: cmd = oP12Import; break; case oP12Import: cmd = oP12Import; break;
case oP12Export: cmd = oP12Export; break; case oP12Export: cmd = oP12Export; break;
case oP12Charset: opt_p12_charset = pargs.r.ret_str; break;
case oPassphrase: opt_passphrase = pargs.r.ret_str; break; case oPassphrase: opt_passphrase = pargs.r.ret_str; break;
case oStore: opt_store = 1; break; case oStore: opt_store = 1; break;

View File

@ -233,11 +233,11 @@ a few informational lines are prepended before each block.
@item --export-secret-key-p12 @var{key-id} @item --export-secret-key-p12 @var{key-id}
@opindex export @opindex export
Export the private key and the certificate identified by @var{key-id} Export the private key and the certificate identified by @var{key-id} in
in a PKCS#12 format. When using along with the @code{--armor} option a PKCS#12 format. When using along with the @code{--armor} option a few
a few informational lines are prepended to the output. Note, that the informational lines are prepended to the output. Note, that the PKCS#12
PKCS#12 format is higly insecure and this command is only provided if format is not very secure and this command is only provided if there is
there is no other way to exchange the private key. no other way to exchange the private key. (@pxref{option --p12-charset})
@item --import [@var{files}] @item --import [@var{files}]
@opindex import @opindex import
@ -437,6 +437,19 @@ Assume the input data is plain base-64 encoded.
@opindex assume-binary @opindex assume-binary
Assume the input data is binary encoded. Assume the input data is binary encoded.
@anchor{option --p12-charset}
@item --p12-charset @var{name}
@opindex p12-charset
@command{gpgsm} uses the UTF-8 encoding when encoding passphrases for
PKCS#12 files. This option may be used to force the passphrase to be
encoded in the specified encoding @var{name}. This is useful if the
application used to import the key uses a different encoding and thus
won't be able to import a file generated by @command{gpgsm}. Commonly
used values for @var{name} are @code{Latin1} and @code{CP850}. Note
that @command{gpgsm} itself automagically imports any file with a
passphrase encoded to the most commonly used encodings.
@item --local-user @var{user_id} @item --local-user @var{user_id}
@item -u @var{user_id} @item -u @var{user_id}
@opindex local-user @opindex local-user

View File

@ -1,3 +1,9 @@
2007-03-20 Werner Koch <wk@g10code.com>
* gpgsm.c: Add option --p12-charset.
* gpgsm.h (struct opt): Add p12_charset.
* export.c (popen_protect_tool): Use new option.
2007-03-19 Werner Koch <wk@g10code.com> 2007-03-19 Werner Koch <wk@g10code.com>
Changes to let export and key listing use estream to help systems Changes to let export and key listing use estream to help systems

View File

@ -416,6 +416,12 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp)
putc ('\n', fp); putc ('\n', fp);
} }
if (opt.p12_charset)
{
fprintf (fp, "The passphrase is %s encoded.\n\n",
opt.p12_charset);
}
ctrl->pem_name = "PKCS12"; ctrl->pem_name = "PKCS12";
rc = gpgsm_create_writer (&b64writer, ctrl, fp, NULL, &writer); rc = gpgsm_create_writer (&b64writer, ctrl, fp, NULL, &writer);
if (rc) if (rc)
@ -567,6 +573,11 @@ popen_protect_tool (const char *pgmname,
argv[i++] = "--prompt"; argv[i++] = "--prompt";
argv[i++] = prompt?prompt:""; argv[i++] = prompt?prompt:"";
argv[i++] = "--enable-status-msg"; argv[i++] = "--enable-status-msg";
if (opt.p12_charset)
{
argv[i++] = "--p12-charset";
argv[i++] = opt.p12_charset;
}
argv[i++] = "--", argv[i++] = "--",
argv[i++] = keygrip, argv[i++] = keygrip,
argv[i] = NULL; argv[i] = NULL;

View File

@ -131,6 +131,7 @@ enum cmd_and_opt_values {
oBase64, oBase64,
oNoArmor, oNoArmor,
oP12Charset,
oDisableCRLChecks, oDisableCRLChecks,
oEnableCRLChecks, oEnableCRLChecks,
@ -280,6 +281,8 @@ static ARGPARSE_OPTS opts[] = {
{ oArmor, "armor", 0, N_("create ascii armored output")}, { oArmor, "armor", 0, N_("create ascii armored output")},
{ oArmor, "armour", 0, "@" }, { oArmor, "armour", 0, "@" },
{ oBase64, "base64", 0, N_("create base-64 encoded output")}, { oBase64, "base64", 0, N_("create base-64 encoded output")},
{ oP12Charset, "p12-charset", 2, "@" },
{ oAssumeArmor, "assume-armor", 0, N_("assume input is in PEM format")}, { oAssumeArmor, "assume-armor", 0, N_("assume input is in PEM format")},
{ oAssumeBase64, "assume-base64", 0, { oAssumeBase64, "assume-base64", 0,
@ -955,7 +958,7 @@ main ( int argc, char **argv)
set_cmd (&cmd, pargs.r_opt); set_cmd (&cmd, pargs.r_opt);
break; break;
/* output encoding selection */ /* Output encoding selection. */
case oArmor: case oArmor:
ctrl.create_pem = 1; ctrl.create_pem = 1;
break; break;
@ -968,7 +971,11 @@ main ( int argc, char **argv)
ctrl.create_base64 = 0; ctrl.create_base64 = 0;
break; break;
/* Input encoding selection */ case oP12Charset:
opt.p12_charset = pargs.r.ret_str;
break;
/* Input encoding selection. */
case oAssumeArmor: case oAssumeArmor:
ctrl.autodetect_encoding = 0; ctrl.autodetect_encoding = 0;
ctrl.is_pem = 1; ctrl.is_pem = 1;

View File

@ -74,6 +74,10 @@ struct
int armor; /* force base64 armoring (see also ctrl.with_base64) */ int armor; /* force base64 armoring (see also ctrl.with_base64) */
int no_armor; /* don't try to figure out whether data is base64 armored*/ int no_armor; /* don't try to figure out whether data is base64 armored*/
const char *p12_charset; /* Use this charset for encoding the
pkcs#12 passphrase. */
const char *def_cipher_algoid; /* cipher algorithm to use if const char *def_cipher_algoid; /* cipher algorithm to use if
nothing else is specified */ nothing else is specified */