diff options
Diffstat (limited to '')
-rw-r--r-- | agent/minip12.c | 71 |
1 files changed, 65 insertions, 6 deletions
diff --git a/agent/minip12.c b/agent/minip12.c index d6029f7b0..6958e5e1d 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -28,11 +28,11 @@ #include <assert.h> #include <gcrypt.h> #include <iconv.h> +#include <errno.h> #ifdef TEST #include <sys/stat.h> #include <unistd.h> -#include <errno.h> #endif #include "../jnlib/logging.h" @@ -518,6 +518,10 @@ decrypt_block (const void *ciphertext, unsigned char *plaintext, size_t length, "ISO-8859-8", "ISO-8859-9", "KOI8-R", + "IBM437", + "IBM850", + "EUC-JP", + "BIG5", NULL }; 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 - PW. Create a PKCS structure from it and return it as well as the - length in R_LENGTH; return NULL in case of an error. */ +/* Expect the RSA key parameters in KPARMS and a password in PW. + Create a PKCS structure from it and return it as well as the length + in R_LENGTH; return NULL in case of an error. If CHARSET is not + NULL, re-encode PW to that character set. */ unsigned char * 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; char salt[8]; struct buffer_s seqlist[3]; int seqlistidx = 0; unsigned char sha1hash[20]; char keyidstr[8+1]; + char *pwbuf = NULL; + size_t pwbufsize = 0; n = buflen = 0; /* (avoid compiler warning). */ memset (sha1hash, 0, 20); *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) { /* 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); failure: + if (pwbuf) + { + wipememory (pwbuf, pwbufsize); + gcry_free (pwbuf); + } for ( ; seqlistidx; seqlistidx--) gcry_free (seqlist[seqlistidx].buffer); |