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;
}

Reply via email to