From 647ac8d3d7143e3721d55e1f57730b6f26e72fc9 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 24 Aug 2016 18:55:51 +0100 Subject: [PATCH] Support broken PKCS#12 key generation. OpenSSL versions before 1.1.0 didn't convert non-ASCII UTF8 PKCS#12 passwords to Unicode correctly. To correctly decrypt older files, if MAC verification fails with the supplied password attempt to use the broken format which is compatible with earlier versions of OpenSSL. Reviewed-by: Richard Levitte --- apps/pkcs12.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/apps/pkcs12.c b/apps/pkcs12.c index f8806b9a6a..93489d6a56 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -132,7 +132,7 @@ int pkcs12_main(int argc, char **argv) int noprompt = 0; char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL; char *passin = NULL, *passout = NULL, *inrand = NULL, *macalg = NULL; - char *cpass = NULL, *mpass = NULL; + char *cpass = NULL, *mpass = NULL, *badpass = NULL; const char *CApath = NULL, *CAfile = NULL, *prog; int noCApath = 0, noCAfile = 0; ENGINE *e = NULL; @@ -539,9 +539,27 @@ int pkcs12_main(int argc, char **argv) if (!twopass) cpass = NULL; } else if (!PKCS12_verify_mac(p12, mpass, -1)) { - BIO_printf(bio_err, "Mac verify error: invalid password?\n"); - ERR_print_errors(bio_err); - goto end; + /* + * May be UTF8 from previous version of OpenSSL: + * convert to a UTF8 form which will translate + * to the same Unicode password. + */ + unsigned char *utmp; + int utmplen; + utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen); + if (utmp == NULL) + goto end; + badpass = OPENSSL_uni2utf8(utmp, utmplen); + OPENSSL_free(utmp); + if (!PKCS12_verify_mac(p12, badpass, -1)) { + BIO_printf(bio_err, "Mac verify error: invalid password?\n"); + ERR_print_errors(bio_err); + goto end; + } else { + BIO_printf(bio_err, "Warning: using broken algorithm\n"); + if (!twopass) + cpass = badpass; + } } } @@ -559,6 +577,7 @@ int pkcs12_main(int argc, char **argv) BIO_free(in); BIO_free_all(out); sk_OPENSSL_STRING_free(canames); + OPENSSL_free(badpass); OPENSSL_free(passin); OPENSSL_free(passout); return (ret); -- 2.34.1