The following bug has been reproduced on RedHat Enterprise Linux with OpenSSL 1.0.1e.
When upgrading from 0.9.8e to 1.0.1e we noticed that a call to PKCS12_parse() would sometimes fail with the following: 3073869560:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:535: 3073869560:error:23077074:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 cipherfinal error:p12_decr.c:97: 3073869560:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:p12_decr.c:123: 3073869560:error:23076072:PKCS12 routines:PKCS12_parse:parse error:p12_kiss.c:129: We determined that the cause was an existing PBE registration within our application via EVP_PBE_alg_add(): EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc(), EVP_sha1(), PKCS12_PBE_keyivgen); Under OpenSSL 1.0.0 and beyond, this causes a PBE to be added with a cipher NID of RC2-CBC instead of RC2-40-CBC. A change to this API uses an incorrect cipher NID returned by EVP_CIPHER_type(). The decryption of PKCS12 components that are encrypted with RC2-40-CBC fails because RC2-CBC is used instead. Enclosed is a modified version of demos/pkcs12/pkread.c. When linked against OpenSSL 1.x.x the code will fail to decrypt a PKCS12 file encrypted with RC2-40-CBC. The same code works fine when linked against 0.9.8*. The code can be made to work with 1.x.x by removing the call to EVP_PBE_alg_add(), allowing the builtin version of this PBE (with the correct cipher NID) to be used. Thank you. Doug Gibbons | Consulting Engineer | Avaya Inc. | 1300 W. 120th Ave | B3-C61 | Westminster, CO 80234 | 303-538-3538 | ldgibb...@avaya.com<mailto:ldgibb...@avaya.com>
/* pkread.c */ #include <stdio.h> #include <stdlib.h> #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/pkcs12.h> /* Simple PKCS#12 file reader */ int main(int argc, char **argv) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; if (argc != 4) { fprintf(stderr, "Usage: pkread p12file password opfile\n"); exit (1); } OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); #if 1 /* With OpenSSL 1.x.x next line creates PBE with incorrect cipher NID */ EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc(), EVP_sha1(), PKCS12_PBE_keyivgen); #endif if (!(fp = fopen(argv[1], "rb"))) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(1); } p12 = d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { fprintf(stderr, "Error reading PKCS#12 file\n"); ERR_print_errors_fp(stderr); exit (1); } if (!PKCS12_parse(p12, argv[2], &pkey, &cert, &ca)) { fprintf(stderr, "Error parsing PKCS#12 file\n"); ERR_print_errors_fp(stderr); exit (1); } PKCS12_free(p12); if (!(fp = fopen(argv[3], "w"))) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(1); } if (pkey) { fprintf(fp, "***Private Key***\n"); PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL); } if (cert) { fprintf(fp, "***User Certificate***\n"); PEM_write_X509_AUX(fp, cert); } if (ca && sk_X509_num(ca)) { fprintf(fp, "***Other Certificates***\n"); for (i = 0; i < sk_X509_num(ca); i++) PEM_write_X509_AUX(fp, sk_X509_value(ca, i)); } fclose(fp); return 0; }