With OpenSSL 0.9.8n this test program segfaults the second time it tries to parse the PKCS#12 file. It was fixed for OpenSSL 1.0.0 by this commit: http://cvs.openssl.org/chngview?cn=17957
Starting program: /home/dwmw2/p12test .cert/certificate.p12 Enter PKCS#12 passphrase: 140737353934504:error:23076071:PKCS12 routines:PKCS12_parse:mac verify failure:p12_kiss.c:121: Parse PKCS#12 failed (wrong passphrase?) Enter PKCS#12 passphrase: Program received signal SIGSEGV, Segmentation fault. __libc_free (mem=0x31) at malloc.c:3709 3709 if (chunk_is_mmapped(p)) /* release mmapped memory. */ (gdb) bt #0 __libc_free (mem=0x31) at malloc.c:3709 #1 0x0000000000417d5d in CRYPTO_free () #2 0x000000000044396d in ASN1_STRING_free () #3 0x000000000043f2cd in ASN1_primitive_free () #4 0x000000000043f69f in ASN1_template_free () #5 0x000000000043f586 in asn1_item_combine_free () #6 0x000000000043f6d5 in ASN1_item_free () #7 0x000000000042e2b4 in sk_pop_free () #8 0x000000000045d643 in PKCS12_parse () #9 0x0000000000401c69 in main () My dirty workaround for now is just to add a deliberate memory leak in my application just before the 'goto retry': #if OPENSSL_VERSION_NUMBER < 0x10000002 ca = sk_X509_new_null(); #endif Any better suggestions? I still stand by everything I said in http://www.advogato.org/person/dwmw2/diary/205.html about loading certificates, FWIW. -- dwmw2
#include <stdio.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/engine.h> #include <openssl/evp.h> #include <openssl/pkcs12.h> #include <openssl/x509v3.h> int main(int argc, char **argv) { FILE *f; EVP_PKEY *pkey = NULL; char pass[PEM_BUFSIZE]; X509 *cert = NULL; PKCS12 *p12; STACK_OF(X509) *ca; SSL_library_init(); ERR_clear_error(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); if (argc != 2) { fprintf(stderr, "Need PKCS#12 filename\n"); exit(1); }; f = fopen(argv[1], "r"); if (!f) { perror("fopen"); exit(1); } p12 = d2i_PKCS12_fp(f, NULL); if (!p12) { fprintf(stderr, "d2i_PKCS12_fp failed\n"); exit(1); } ca = sk_X509_new_null(); retry: if (EVP_read_pw_string(pass, PEM_BUFSIZE, "Enter PKCS#12 passphrase:", 0)) { fprintf(stderr, "Failed to obtain passphrase\n"); exit(1); } if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { unsigned long err = ERR_peek_error(); ERR_print_errors_fp(stderr); if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 && ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE && ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) { fprintf(stderr, "Parse PKCS#12 failed (wrong passphrase?)\n"); goto retry; } fprintf(stderr, "Failed\n"); exit(1); } printf("Succeeded\n"); return 0; }