Additional user data argument to pem_password_cb function type
and to lots of PEM_... functions.
Submitted by: Damien Miller <dmiller@ilogic.com.au>
diff --git a/CHANGES b/CHANGES
index d481e6e..108675f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,7 +2,27 @@
  OpenSSL CHANGES
  _______________
 
- Changes between 0.9.3a and 0.9.4
+ Changes between 0.9.3a and 0.9.4  [xx Jul/Aug/...? 1999]
+
+  *) pem_password_cb function type incompatibly changed from
+          typedef int pem_password_cb(char *buf, int size, int rwflag);
+     to
+          ....(char *buf, int size, int rwflag, void *userdata);
+     so that applications can pass data to their callbacks:
+     The PEM[_ASN1]_{read,write}... functions and macros now take an
+     additional void * argument, which is just handed through whenever
+     the password callback is called.
+     [Damien Miller <dmiller@ilogic.com.au>, with tiny changes by Bodo Moeller]
+
+     New function SSL_CTX_set_default_passwd_cb_userdata.
+
+     Compatibility note: As many C implementations push function arguments
+     onto the stack in reverse order, the new library version is likely to
+     interoperate with programs that have been compiled with the old
+     pem_password_cb definition (PEM_whatever takes some data that
+     happens to be on the stack as its last argument, and the callback
+     just ignores this garbage); but there is no guarantee whatsoever that
+     this will work.
 
   *) The -DPLATFORM="\"$(PLATFORM)\"" definition and the similar -DCFLAGS=...
      (both in crypto/Makefile.ssl for use by crypto/cversion.c) caused
diff --git a/apps/ca.c b/apps/ca.c
index 6a86438..26b86de 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -499,10 +499,10 @@
 		goto err;
 		}
 	if (key == NULL)
-		pkey=PEM_read_bio_PrivateKey(in,NULL,NULL);
+		pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL);
 	else
 		{
-		pkey=PEM_read_bio_PrivateKey(in,NULL,key_callback);
+		pkey=PEM_read_bio_PrivateKey(in,NULL,key_callback,NULL);
 		memset(key,0,strlen(key));
 		}
 	if (pkey == NULL)
@@ -525,7 +525,7 @@
 		BIO_printf(bio_err,"trying to load CA certificate\n");
 		goto err;
 		}
-	x509=PEM_read_bio_X509(in,NULL,NULL);
+	x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
 	if (x509 == NULL)
 		{
 		BIO_printf(bio_err,"unable to load CA certificate\n");
@@ -1146,7 +1146,7 @@
 				BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
 				goto err;
 				}
-			x509=PEM_read_bio_X509(in,NULL,NULL);
+			x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
 			if (x509 == NULL)
 				{
 				BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
@@ -1340,7 +1340,7 @@
 		perror(infile);
 		goto err;
 		}
-	if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL)) == NULL)
+	if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
 		{
 		BIO_printf(bio_err,"Error reading certificate request in %s\n",
 			infile);
@@ -1400,7 +1400,7 @@
 		perror(infile);
 		goto err;
 		}
-	if ((req=PEM_read_bio_X509(in,NULL,NULL)) == NULL)
+	if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
 		{
 		BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
 		goto err;
diff --git a/apps/crl.c b/apps/crl.c
index 1b04f68..f7bdf76 100644
--- a/apps/crl.c
+++ b/apps/crl.c
@@ -280,7 +280,7 @@
 	if 	(format == FORMAT_ASN1)
 		x=d2i_X509_CRL_bio(in,NULL);
 	else if (format == FORMAT_PEM)
-		x=PEM_read_bio_X509_CRL(in,NULL,NULL);
+		x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
 	else	{
 		BIO_printf(bio_err,"bad input format specified for input crl\n");
 		goto end;
diff --git a/apps/crl2p7.c b/apps/crl2p7.c
index f4b216f..8634e3a 100644
--- a/apps/crl2p7.c
+++ b/apps/crl2p7.c
@@ -193,7 +193,7 @@
 		if 	(informat == FORMAT_ASN1)
 			crl=d2i_X509_CRL_bio(in,NULL);
 		else if (informat == FORMAT_PEM)
-			crl=PEM_read_bio_X509_CRL(in,NULL,NULL);
+			crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
 		else	{
 			BIO_printf(bio_err,"bad input format specified for input crl\n");
 			goto end;
@@ -304,7 +304,7 @@
 		}
 
 	/* This loads from a file, a stack of x509/crl/pkey sets */
-	sk=PEM_X509_INFO_read_bio(in,NULL,NULL);
+	sk=PEM_X509_INFO_read_bio(in,NULL,NULL,NULL);
 	if (sk == NULL) {
 		BIO_printf(bio_err,"error reading the file, %s\n",certfile);
 		goto end;
diff --git a/apps/dh.c b/apps/dh.c
index b4abbe7..9efdcd7 100644
--- a/apps/dh.c
+++ b/apps/dh.c
@@ -194,7 +194,7 @@
 	if	(informat == FORMAT_ASN1)
 		dh=d2i_DHparams_bio(in,NULL);
 	else if (informat == FORMAT_PEM)
-		dh=PEM_read_bio_DHparams(in,NULL,NULL);
+		dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL);
 	else
 		{
 		BIO_printf(bio_err,"bad input format specified\n");
diff --git a/apps/dsa.c b/apps/dsa.c
index 977955a..fedecf2 100644
--- a/apps/dsa.c
+++ b/apps/dsa.c
@@ -191,7 +191,7 @@
 	if	(informat == FORMAT_ASN1)
 		dsa=d2i_DSAPrivateKey_bio(in,NULL);
 	else if (informat == FORMAT_PEM)
-		dsa=PEM_read_bio_DSAPrivateKey(in,NULL,NULL);
+		dsa=PEM_read_bio_DSAPrivateKey(in,NULL,NULL,NULL);
 	else
 		{
 		BIO_printf(bio_err,"bad input format specified for key\n");
@@ -235,7 +235,7 @@
 	if 	(outformat == FORMAT_ASN1)
 		i=i2d_DSAPrivateKey_bio(out,dsa);
 	else if (outformat == FORMAT_PEM)
-		i=PEM_write_bio_DSAPrivateKey(out,dsa,enc,NULL,0,NULL);
+		i=PEM_write_bio_DSAPrivateKey(out,dsa,enc,NULL,0,NULL,NULL);
 	else	{
 		BIO_printf(bio_err,"bad output format specified for outfile\n");
 		goto end;
diff --git a/apps/dsaparam.c b/apps/dsaparam.c
index be653a3..fb8d471 100644
--- a/apps/dsaparam.c
+++ b/apps/dsaparam.c
@@ -220,7 +220,7 @@
 	else if	(informat == FORMAT_ASN1)
 		dsa=d2i_DSAparams_bio(in,NULL);
 	else if (informat == FORMAT_PEM)
-		dsa=PEM_read_bio_DSAparams(in,NULL,NULL);
+		dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL);
 	else
 		{
 		BIO_printf(bio_err,"bad input format specified\n");
@@ -321,7 +321,7 @@
 		if 	(outformat == FORMAT_ASN1)
 			i=i2d_DSAPrivateKey_bio(out,dsakey);
 		else if (outformat == FORMAT_PEM)
-			i=PEM_write_bio_DSAPrivateKey(out,dsakey,NULL,NULL,0,NULL);
+			i=PEM_write_bio_DSAPrivateKey(out,dsakey,NULL,NULL,0,NULL,NULL);
 		else	{
 			BIO_printf(bio_err,"bad output format specified for outfile\n");
 			goto end;
diff --git a/apps/gendsa.c b/apps/gendsa.c
index bf18673..dc0b216 100644
--- a/apps/gendsa.c
+++ b/apps/gendsa.c
@@ -155,7 +155,7 @@
 		goto end;
 		}
 
-	if ((dsa=PEM_read_bio_DSAparams(in,NULL,NULL)) == NULL)
+	if ((dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
 		{
 		BIO_printf(bio_err,"unable to load DSA parameter file\n");
 		goto end;
@@ -197,7 +197,7 @@
 	else
 		RAND_write_file(randfile);
 
-	if (!PEM_write_bio_DSAPrivateKey(out,dsa,enc,NULL,0,NULL))
+	if (!PEM_write_bio_DSAPrivateKey(out,dsa,enc,NULL,0,NULL,NULL))
 		goto end;
 	ret=0;
 end:
diff --git a/apps/genrsa.c b/apps/genrsa.c
index cc4f786..6738206 100644
--- a/apps/genrsa.c
+++ b/apps/genrsa.c
@@ -215,7 +215,7 @@
 		l+=rsa->e->d[i];
 		}
 	BIO_printf(bio_err,"e is %ld (0x%lX)\n",l,l);
-	if (!PEM_write_bio_RSAPrivateKey(out,rsa,enc,NULL,0,NULL))
+	if (!PEM_write_bio_RSAPrivateKey(out,rsa,enc,NULL,0,NULL,NULL))
 		goto err;
 
 	ret=0;
diff --git a/apps/nseq.c b/apps/nseq.c
index e7f33af..d9d0165 100644
--- a/apps/nseq.c
+++ b/apps/nseq.c
@@ -124,7 +124,7 @@
 	if (toseq) {
 		seq = NETSCAPE_CERT_SEQUENCE_new();
 		seq->certs = sk_X509_new(NULL);
-		while((x509 = PEM_read_bio_X509(in, NULL, NULL))) 
+		while((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) 
 		    sk_X509_push(seq->certs,x509);
 
 		if(!sk_X509_num(seq->certs))
@@ -138,7 +138,7 @@
 		goto end;
 	}
 
-	if (!(seq = PEM_read_bio_NETSCAPE_CERT_SEQUENCE(in, NULL, NULL))) {
+	if (!(seq = PEM_read_bio_NETSCAPE_CERT_SEQUENCE(in, NULL, NULL, NULL))) {
 		BIO_printf (bio_err, "Error reading sequence file %s\n", infile);
 		ERR_print_errors(bio_err);
 		goto end;
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 45d9797..f3f82dd 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -292,7 +292,7 @@
 	unsigned char keyid[EVP_MAX_MD_SIZE];
 	unsigned int keyidlen;
 	/* Get private key so we can match it to a certificate */
-	key = PEM_read_bio_PrivateKey(inkey ? inkey : in, NULL, NULL);
+	key = PEM_read_bio_PrivateKey(inkey ? inkey : in, NULL, NULL, NULL);
 	if (!inkey) (void)BIO_reset(in);
 	if (!key) {
 		BIO_printf (bio_err, "Error loading private key\n");
@@ -531,7 +531,7 @@
 		p8 = bag->value.keybag;
 		if (!(pkey = EVP_PKCS82PKEY (p8))) return 0;
 		print_attribs (out, p8->attributes, "Key Attributes");
-		PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL);
+		PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, NULL);
 		EVP_PKEY_free(pkey);
 	break;
 
@@ -547,7 +547,7 @@
 		if (!(pkey = EVP_PKCS82PKEY (p8))) return 0;
 		print_attribs (out, p8->attributes, "Key Attributes");
 		PKCS8_PRIV_KEY_INFO_free(p8);
-		PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL);
+		PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, NULL);
 		EVP_PKEY_free(pkey);
 	break;
 
@@ -633,7 +633,7 @@
 	int ret;
 	X509 *cert;
 	ret = 0;
-	while((cert = PEM_read_bio_X509(in, NULL, NULL))) {
+	while((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
 		ret = 1;
 		sk_X509_push(sk, cert);
 	}
diff --git a/apps/pkcs7.c b/apps/pkcs7.c
index 9518983..0e1427c 100644
--- a/apps/pkcs7.c
+++ b/apps/pkcs7.c
@@ -195,7 +195,7 @@
 	if	(informat == FORMAT_ASN1)
 		p7=d2i_PKCS7_bio(in,NULL);
 	else if (informat == FORMAT_PEM)
-		p7=PEM_read_bio_PKCS7(in,NULL,NULL);
+		p7=PEM_read_bio_PKCS7(in,NULL,NULL,NULL);
 	else
 		{
 		BIO_printf(bio_err,"bad input format specified for pkcs7 object\n");
diff --git a/apps/pkcs8.c b/apps/pkcs8.c
index 9779081..9e9b92b 100644
--- a/apps/pkcs8.c
+++ b/apps/pkcs8.c
@@ -160,7 +160,7 @@
 	} else out = BIO_new_fp (stdout, BIO_NOCLOSE);
 
 	if (topk8) {
-		if (!(pkey = PEM_read_bio_PrivateKey(in, NULL, NULL))) {
+		if (!(pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL))) {
 			BIO_printf (bio_err, "Error reading key\n", outfile);
 			ERR_print_errors(bio_err);
 			return (1);
@@ -209,7 +209,7 @@
 
 	if(nocrypt) {
 		if(informat == FORMAT_PEM) 
-			p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in,NULL,NULL);
+			p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in,NULL,NULL, NULL);
 		else if(informat == FORMAT_ASN1)
 			p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
 		else {
@@ -218,7 +218,7 @@
 		}
 	} else {
 		if(informat == FORMAT_PEM) 
-			p8 = PEM_read_bio_PKCS8(in, NULL, NULL);
+			p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
 		else if(informat == FORMAT_ASN1)
 			p8 = d2i_PKCS8_bio(in, NULL);
 		else {
@@ -263,7 +263,7 @@
 	
 	PKCS8_PRIV_KEY_INFO_free(p8inf);
 
-	PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL);
+	PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, NULL);
 
 	EVP_PKEY_free(pkey);
 	BIO_free(out);
diff --git a/apps/req.c b/apps/req.c
index 86c29e0..463ac15 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -242,11 +242,11 @@
 					perror(p);
 					goto end;
 					}
-				if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL)) == NULL)
+				if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
 					{
 					ERR_clear_error();
 					(void)BIO_reset(in);
-					if ((xtmp=PEM_read_bio_X509(in,NULL,NULL)) == NULL)
+					if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
 						{
 						BIO_printf(bio_err,"unable to load DSA parameters from file\n");
 						goto end;
@@ -455,7 +455,7 @@
 			rsa=d2i_RSAPrivateKey_bio(in,NULL);
 		else */
 		if (keyform == FORMAT_PEM)
-			pkey=PEM_read_bio_PrivateKey(in,NULL,NULL);
+			pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL);
 		else
 			{
 			BIO_printf(bio_err,"bad input format specified for X509 request\n");
@@ -560,7 +560,7 @@
 		i=0;
 loop:
 		if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
-			NULL,0,NULL))
+			NULL,0,NULL,NULL))
 			{
 			if ((ERR_GET_REASON(ERR_peek_error()) ==
 				PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
@@ -594,7 +594,7 @@
 		if	(informat == FORMAT_ASN1)
 			req=d2i_X509_REQ_bio(in,NULL);
 		else if (informat == FORMAT_PEM)
-			req=PEM_read_bio_X509_REQ(in,NULL,NULL);
+			req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
 		else
 			{
 			BIO_printf(bio_err,"bad input format specified for X509 request\n");
diff --git a/apps/rsa.c b/apps/rsa.c
index 07c14e2..9b723ee 100644
--- a/apps/rsa.c
+++ b/apps/rsa.c
@@ -222,7 +222,7 @@
 		}
 #endif
 	else if (informat == FORMAT_PEM)
-		rsa=PEM_read_bio_RSAPrivateKey(in,NULL,NULL);
+		rsa=PEM_read_bio_RSAPrivateKey(in,NULL,NULL,NULL);
 	else
 		{
 		BIO_printf(bio_err,"bad input format specified for key\n");
@@ -312,7 +312,7 @@
 		}
 #endif
 	else if (outformat == FORMAT_PEM)
-		i=PEM_write_bio_RSAPrivateKey(out,rsa,enc,NULL,0,NULL);
+		i=PEM_write_bio_RSAPrivateKey(out,rsa,enc,NULL,0,NULL,NULL);
 	else	{
 		BIO_printf(bio_err,"bad output format specified for outfile\n");
 		goto end;
diff --git a/apps/s_server.c b/apps/s_server.c
index 4b932ba..5b07918 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -1027,7 +1027,7 @@
 
 	if ((bio=BIO_new_file(DH_PARAM,"r")) == NULL)
 		goto err;
-	ret=PEM_read_bio_DHparams(bio,NULL,NULL);
+	ret=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);
 err:
 	if (bio != NULL) BIO_free(bio);
 	return(ret);
diff --git a/apps/sess_id.c b/apps/sess_id.c
index eb84e25..8ac118d 100644
--- a/apps/sess_id.c
+++ b/apps/sess_id.c
@@ -289,7 +289,7 @@
 	if 	(format == FORMAT_ASN1)
 		x=d2i_SSL_SESSION_bio(in,NULL);
 	else if (format == FORMAT_PEM)
-		x=PEM_read_bio_SSL_SESSION(in,NULL,NULL);
+		x=PEM_read_bio_SSL_SESSION(in,NULL,NULL,NULL);
 	else	{
 		BIO_printf(bio_err,"bad input format specified for input crl\n");
 		goto end;
diff --git a/apps/verify.c b/apps/verify.c
index 119709f..093fe09 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -171,7 +171,7 @@
 			}
 		}
 
-	x=PEM_read_bio_X509(in,NULL,NULL);
+	x=PEM_read_bio_X509(in,NULL,NULL,NULL);
 	if (x == NULL)
 		{
 		fprintf(stdout,"%s: unable to load certificate file\n",
diff --git a/apps/x509.c b/apps/x509.c
index 1024c0d..2e2d18b 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -377,7 +377,7 @@
 				goto end;
 				}
 			}
-		req=PEM_read_bio_X509_REQ(in,NULL,NULL);
+		req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
 		BIO_free(in);
 
 		if (req == NULL) { perror(infile); goto end; }
@@ -948,7 +948,7 @@
 #endif
 		if (format == FORMAT_PEM)
 		{
-		pkey=PEM_read_bio_PrivateKey(key,NULL,NULL);
+		pkey=PEM_read_bio_PrivateKey(key,NULL,NULL,NULL);
 		}
 	else
 		{
@@ -1031,7 +1031,7 @@
 		ah->data=NULL;
 		}
 	else if (format == FORMAT_PEM)
-		x=PEM_read_bio_X509(cert,NULL,NULL);
+		x=PEM_read_bio_X509(cert,NULL,NULL,NULL);
 	else	{
 		BIO_printf(bio_err,"bad input format specified for input cert\n");
 		goto end;
diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h
index 0ce05cc..5017a87 100644
--- a/crypto/pem/pem.h
+++ b/crypto/pem/pem.h
@@ -198,48 +198,50 @@
 #else
 
 #define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
-type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb)\
+type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
 { \
-return((type *)PEM_ASN1_read((char *(*)())d2i_##asn1, str,fp,(char **)x,cb)); \
+return((type *)PEM_ASN1_read((char *(*)())d2i_##asn1, str,fp,(char **)x,\
+	cb,u)); \
 } \
 
 #define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
 int PEM_write_##name(FILE *fp, type *x) \
 { \
 return(PEM_ASN1_write((int (*)())i2d_##asn1,str,fp, (char *)x, \
-							 NULL,NULL,0,NULL)); \
+							 NULL,NULL,0,NULL,NULL)); \
 } 
 
 #define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
 int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
-	     unsigned char *kstr, int klen, pem_password_cb *cb) \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, \
+		  void *u) \
 	{ \
 	return(PEM_ASN1_write((int (*)())i2d_##asn1,str,fp, \
-		(char *)x,enc,kstr,klen,cb)); \
+		(char *)x,enc,kstr,klen,cb,u)); \
 	}
 
 #endif
 
 #define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
-type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb)\
+type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
 { \
 return((type *)PEM_ASN1_read_bio((char *(*)())d2i_##asn1, str,bp,\
-							(char **)x,cb)); \
+							(char **)x,cb,u)); \
 }
 
 #define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
 int PEM_write_bio_##name(BIO *bp, type *x) \
 { \
 return(PEM_ASN1_write_bio((int (*)())i2d_##asn1,str,bp, (char *)x, \
-							 NULL,NULL,0,NULL)); \
+							 NULL,NULL,0,NULL,NULL)); \
 }
 
 #define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
 int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
-	     unsigned char *kstr, int klen, pem_password_cb *cb) \
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
 	{ \
 	return(PEM_ASN1_write_bio((int (*)())i2d_##asn1,str,bp, \
-		(char *)x,enc,kstr,klen,cb)); \
+		(char *)x,enc,kstr,klen,cb,u)); \
 	}
 
 #define IMPLEMENT_PEM_write(name, type, str, asn1) \
@@ -273,27 +275,27 @@
 #else
 
 #define DECLARE_PEM_read_fp(name, type) \
-	type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb);
+	type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u);
 
 #define DECLARE_PEM_write_fp(name, type) \
 	int PEM_write_##name(FILE *fp, type *x);
 
 #define DECLARE_PEM_write_cb_fp(name, type) \
 	int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
-	     unsigned char *kstr, int klen, pem_password_cb *cb);
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
 
 #endif
 
 #ifdef HEADER_BIO_H
 #define DECLARE_PEM_read_bio(name, type) \
-	type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb);
+	type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u);
 
 #define DECLARE_PEM_write_bio(name, type) \
 	int PEM_write_bio_##name(BIO *bp, type *x);
 
 #define DECLARE_PEM_write_cb_bio(name, type) \
 	int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
-	     unsigned char *kstr, int klen, pem_password_cb *cb);
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
 
 #else
 
@@ -327,146 +329,150 @@
 
 #define PEM_write_SSL_SESSION(fp,x) \
 		PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
-			PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL)
+			PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_X509(fp,x) \
 		PEM_ASN1_write((int (*)())i2d_X509,PEM_STRING_X509,fp, \
-			(char *)x, NULL,NULL,0,NULL)
+			(char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_X509_REQ(fp,x) PEM_ASN1_write( \
 		(int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,fp,(char *)x, \
-			NULL,NULL,0,NULL)
+			NULL,NULL,0,NULL,NULL)
 #define PEM_write_X509_CRL(fp,x) \
 		PEM_ASN1_write((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL, \
-			fp,(char *)x, NULL,NULL,0,NULL)
-#define	PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb) \
+			fp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define	PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
 		PEM_ASN1_write((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,fp,\
-			(char *)x,enc,kstr,klen,cb)
+			(char *)x,enc,kstr,klen,cb,u)
 #define	PEM_write_RSAPublicKey(fp,x) \
 		PEM_ASN1_write((int (*)())i2d_RSAPublicKey,\
-			PEM_STRING_RSA_PUBLIC,fp,(char *)x,NULL,NULL,0,NULL)
-#define	PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb) \
+			PEM_STRING_RSA_PUBLIC,fp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define	PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb,u) \
 		PEM_ASN1_write((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,fp,\
-			(char *)x,enc,kstr,klen,cb)
-#define	PEM_write_PrivateKey(bp,x,enc,kstr,klen,cb) \
+			(char *)x,enc,kstr,klen,cb,u)
+#define	PEM_write_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
 		PEM_ASN1_write((int (*)())i2d_PrivateKey,\
 		(((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
-			bp,(char *)x,enc,kstr,klen,cb)
+			bp,(char *)x,enc,kstr,klen,cb,u)
 #define PEM_write_PKCS7(fp,x) \
 		PEM_ASN1_write((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,fp, \
-			(char *)x, NULL,NULL,0,NULL)
+			(char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_DHparams(fp,x) \
 		PEM_ASN1_write((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,fp,\
-			(char *)x,NULL,NULL,0,NULL)
+			(char *)x,NULL,NULL,0,NULL,NULL)
 
 #define PEM_write_NETSCAPE_CERT_SEQUENCE(fp,x) \
                 PEM_ASN1_write((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
 			PEM_STRING_X509,fp, \
-                        (char *)x, NULL,NULL,0,NULL)
+                        (char *)x, NULL,NULL,0,NULL,NULL)
 
-#define	PEM_read_SSL_SESSION(fp,x,cb) (SSL_SESSION *)PEM_ASN1_read( \
-	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb)
-#define	PEM_read_X509(fp,x,cb) (X509 *)PEM_ASN1_read( \
-	(char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb)
-#define	PEM_read_X509_REQ(fp,x,cb) (X509_REQ *)PEM_ASN1_read( \
-	(char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,fp,(char **)x,cb)
-#define	PEM_read_X509_CRL(fp,x,cb) (X509_CRL *)PEM_ASN1_read( \
-	(char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,fp,(char **)x,cb)
-#define	PEM_read_RSAPrivateKey(fp,x,cb) (RSA *)PEM_ASN1_read( \
-	(char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb)
-#define	PEM_read_RSAPublicKey(fp,x,cb) (RSA *)PEM_ASN1_read( \
-	(char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb)
-#define	PEM_read_DSAPrivateKey(fp,x,cb) (DSA *)PEM_ASN1_read( \
-	(char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,fp,(char **)x,cb)
-#define	PEM_read_PrivateKey(fp,x,cb) (EVP_PKEY *)PEM_ASN1_read( \
-	(char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb)
-#define	PEM_read_PKCS7(fp,x,cb) (PKCS7 *)PEM_ASN1_read( \
-	(char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,fp,(char **)x,cb)
-#define	PEM_read_DHparams(fp,x,cb) (DH *)PEM_ASN1_read( \
-	(char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,fp,(char **)x,cb)
+#define	PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define	PEM_read_X509(fp,x,cb,u) (X509 *)PEM_ASN1_read( \
+	(char *(*)())d2i_X509,PEM_STRING_X509,fp,(char **)x,cb,u)
+#define	PEM_read_X509_REQ(fp,x,cb,u) (X509_REQ *)PEM_ASN1_read( \
+	(char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,fp,(char **)x,cb,u)
+#define	PEM_read_X509_CRL(fp,x,cb,u) (X509_CRL *)PEM_ASN1_read( \
+	(char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,fp,(char **)x,cb,u)
+#define	PEM_read_RSAPrivateKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+	(char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,fp,(char **)x,cb,u)
+#define	PEM_read_RSAPublicKey(fp,x,cb,u) (RSA *)PEM_ASN1_read( \
+	(char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,fp,(char **)x,cb,u)
+#define	PEM_read_DSAPrivateKey(fp,x,cb,u) (DSA *)PEM_ASN1_read( \
+	(char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,fp,(char **)x,cb,u)
+#define	PEM_read_PrivateKey(fp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read( \
+	(char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,fp,(char **)x,cb,u)
+#define	PEM_read_PKCS7(fp,x,cb,u) (PKCS7 *)PEM_ASN1_read( \
+	(char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,fp,(char **)x,cb,u)
+#define	PEM_read_DHparams(fp,x,cb,u) (DH *)PEM_ASN1_read( \
+	(char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,fp,(char **)x,cb,u)
 
-#define PEM_read_NETSCAPE_CERT_SEQUENCE(fp,x,cb) \
+#define PEM_read_NETSCAPE_CERT_SEQUENCE(fp,x,cb,u) \
 		(NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read( \
         (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,fp,\
-							(char **)x,cb)
+							(char **)x,cb,u)
 
 #define PEM_write_bio_SSL_SESSION(bp,x) \
 		PEM_ASN1_write_bio((int (*)())i2d_SSL_SESSION, \
-			PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL)
+			PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_X509(bp,x) \
 		PEM_ASN1_write_bio((int (*)())i2d_X509,PEM_STRING_X509,bp, \
-			(char *)x, NULL,NULL,0,NULL)
+			(char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_X509_REQ(bp,x) PEM_ASN1_write_bio( \
 		(int (*)())i2d_X509_REQ,PEM_STRING_X509_REQ,bp,(char *)x, \
-			NULL,NULL,0,NULL)
+			NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_X509_CRL(bp,x) \
 		PEM_ASN1_write_bio((int (*)())i2d_X509_CRL,PEM_STRING_X509_CRL,\
-			bp,(char *)x, NULL,NULL,0,NULL)
-#define	PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb) \
+			bp,(char *)x, NULL,NULL,0,NULL,NULL)
+#define	PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
 		PEM_ASN1_write_bio((int (*)())i2d_RSAPrivateKey,PEM_STRING_RSA,\
-			bp,(char *)x,enc,kstr,klen,cb)
+			bp,(char *)x,enc,kstr,klen,cb,u)
 #define	PEM_write_bio_RSAPublicKey(bp,x) \
 		PEM_ASN1_write_bio((int (*)())i2d_RSAPublicKey, \
 			PEM_STRING_RSA_PUBLIC,\
-			bp,(char *)x,NULL,NULL,0,NULL)
-#define	PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb) \
+			bp,(char *)x,NULL,NULL,0,NULL,NULL)
+#define	PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
 		PEM_ASN1_write_bio((int (*)())i2d_DSAPrivateKey,PEM_STRING_DSA,\
-			bp,(char *)x,enc,kstr,klen,cb)
-#define	PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb) \
+			bp,(char *)x,enc,kstr,klen,cb,u)
+#define	PEM_write_bio_PrivateKey(bp,x,enc,kstr,klen,cb,u) \
 		PEM_ASN1_write_bio((int (*)())i2d_PrivateKey,\
 		(((x)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA),\
-			bp,(char *)x,enc,kstr,klen,cb)
+			bp,(char *)x,enc,kstr,klen,cb,u)
 #define PEM_write_bio_PKCS7(bp,x) \
 		PEM_ASN1_write_bio((int (*)())i2d_PKCS7,PEM_STRING_PKCS7,bp, \
-			(char *)x, NULL,NULL,0,NULL)
+			(char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_DHparams(bp,x) \
 		PEM_ASN1_write_bio((int (*)())i2d_DHparams,PEM_STRING_DHPARAMS,\
-			bp,(char *)x,NULL,NULL,0,NULL)
+			bp,(char *)x,NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_DSAparams(bp,x) \
 		PEM_ASN1_write_bio((int (*)())i2d_DSAparams, \
-			PEM_STRING_DSAPARAMS,bp,(char *)x,NULL,NULL,0,NULL)
+			PEM_STRING_DSAPARAMS,bp,(char *)x,NULL,NULL,0,NULL,NULL)
 
 #define PEM_write_bio_NETSCAPE_CERT_SEQUENCE(bp,x) \
                 PEM_ASN1_write_bio((int (*)())i2d_NETSCAPE_CERT_SEQUENCE, \
 			PEM_STRING_X509,bp, \
-                        (char *)x, NULL,NULL,0,NULL)
+                        (char *)x, NULL,NULL,0,NULL,NULL)
 
-#define	PEM_read_bio_SSL_SESSION(bp,x,cb) (SSL_SESSION *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb)
-#define	PEM_read_bio_X509(bp,x,cb) (X509 *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_X509,PEM_STRING_X509,bp,(char **)x,cb)
-#define	PEM_read_bio_X509_REQ(bp,x,cb) (X509_REQ *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,bp,(char **)x,cb)
-#define	PEM_read_bio_X509_CRL(bp,x,cb) (X509_CRL *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,bp,(char **)x,cb)
-#define	PEM_read_bio_RSAPrivateKey(bp,x,cb) (RSA *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb)
-#define	PEM_read_bio_RSAPublicKey(bp,x,cb) (RSA *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb)
-#define	PEM_read_bio_DSAPrivateKey(bp,x,cb) (DSA *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,bp,(char **)x,cb)
-#define	PEM_read_bio_PrivateKey(bp,x,cb) (EVP_PKEY *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,bp,(char **)x,cb)
+#define	PEM_read_bio_SSL_SESSION(bp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb,u)
+#define	PEM_read_bio_X509(bp,x,cb,u) (X509 *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_X509,PEM_STRING_X509,bp,(char **)x,cb,u)
+#define	PEM_read_bio_X509_REQ(bp,x,cb,u) (X509_REQ *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_X509_REQ,PEM_STRING_X509_REQ,bp,(char **)x,cb,u)
+#define	PEM_read_bio_X509_CRL(bp,x,cb,u) (X509_CRL *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_X509_CRL,PEM_STRING_X509_CRL,bp,(char **)x,cb,u)
+#define	PEM_read_bio_RSAPrivateKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_RSAPrivateKey,PEM_STRING_RSA,bp,(char **)x,cb,u)
+#define	PEM_read_bio_RSAPublicKey(bp,x,cb,u) (RSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_RSAPublicKey,PEM_STRING_RSA_PUBLIC,bp,(char **)x,cb,u)
+#define	PEM_read_bio_DSAPrivateKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_DSAPrivateKey,PEM_STRING_DSA,bp,(char **)x,cb,u)
+#define	PEM_read_bio_PrivateKey(bp,x,cb,u) (EVP_PKEY *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_PrivateKey,PEM_STRING_EVP_PKEY,bp,(char **)x,cb,u)
 
-#define	PEM_read_bio_PKCS7(bp,x,cb) (PKCS7 *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,bp,(char **)x,cb)
-#define	PEM_read_bio_DHparams(bp,x,cb) (DH *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,bp,(char **)x,cb)
-#define	PEM_read_bio_DSAparams(bp,x,cb) (DSA *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_DSAparams,PEM_STRING_DSAPARAMS,bp,(char **)x,cb)
+#define	PEM_read_bio_PKCS7(bp,x,cb,u) (PKCS7 *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_PKCS7,PEM_STRING_PKCS7,bp,(char **)x,cb,u)
+#define	PEM_read_bio_DHparams(bp,x,cb,u) (DH *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_DHparams,PEM_STRING_DHPARAMS,bp,(char **)x,cb,u)
+#define	PEM_read_bio_DSAparams(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_DSAparams,PEM_STRING_DSAPARAMS,bp,(char **)x,cb,u)
 
-#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE(bp,x,cb) \
+#define PEM_read_bio_NETSCAPE_CERT_SEQUENCE(bp,x,cb,u) \
 		(NETSCAPE_CERT_SEQUENCE *)PEM_ASN1_read_bio( \
         (char *(*)())d2i_NETSCAPE_CERT_SEQUENCE,PEM_STRING_X509,bp,\
-							(char **)x,cb)
+							(char **)x,cb,u)
 
 #endif
 
+#if 1
+/* "userdata": new with OpenSSL 0.9.4 */
+typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata);
+#else
+/* OpenSSL 0.9.3, 0.9.3a */
 typedef int pem_password_cb(char *buf, int size, int rwflag);
-/* "size" should be size_t, obviously, but it was always used
- * without a parameter list declaration, which makes it "int" */
+#endif
 
 int	PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher);
 int	PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len,
-	pem_password_cb *);
+	pem_password_cb *callback,void *u);
 
 #ifdef HEADER_BIO_H
 int	PEM_read_bio(BIO *bp, char **name, char **header,
@@ -474,13 +480,13 @@
 int	PEM_write_bio(BIO *bp,const char *name,char *hdr,unsigned char *data,
 		long len);
 char *	PEM_ASN1_read_bio(char *(*d2i)(),const char *name,BIO *bp,char **x,
-		pem_password_cb *);
+		pem_password_cb *cb, void *u);
 int	PEM_ASN1_write_bio(int (*i2d)(),const char *name,BIO *bp,char *x,
 			   const EVP_CIPHER *enc,unsigned char *kstr,int klen,
-			   pem_password_cb *);
-STACK_OF(X509_INFO) *	PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *);
+			   pem_password_cb *cb, void *u);
+STACK_OF(X509_INFO) *	PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
 int	PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc,
-		unsigned char *kstr, int klen, pem_password_cb *);
+		unsigned char *kstr, int klen, pem_password_cb *cd, void *u);
 #endif
 
 #ifndef WIN16
@@ -488,12 +494,12 @@
 		unsigned char **data,long *len);
 int	PEM_write(FILE *fp,char *name,char *hdr,unsigned char *data,long len);
 char *	PEM_ASN1_read(char *(*d2i)(),const char *name,FILE *fp,char **x,
-	pem_password_cb *);
+	pem_password_cb *cb, void *u);
 int	PEM_ASN1_write(int (*i2d)(),const char *name,FILE *fp,char *x,
 		       const EVP_CIPHER *enc,unsigned char *kstr,int klen,
-		       pem_password_cb *);
+		       pem_password_cb *callback, void *u);
 STACK_OF(X509_INFO) *	PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
-	pem_password_cb *);
+	pem_password_cb *cb, void *u);
 #endif
 
 int	PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type,
@@ -565,7 +571,7 @@
 #endif
 
 int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc,
-			      char *kstr,int klen, pem_password_cb *);
+			      char *kstr,int klen, pem_password_cb *cd, void *u);
 #endif /* SSLEAY_MACROS */
 
 
diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c
index ec392ea..fec18a4 100644
--- a/crypto/pem/pem_info.c
+++ b/crypto/pem/pem_info.c
@@ -65,7 +65,7 @@
 #include <openssl/pem.h>
 
 #ifndef NO_FP_API
-STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb)
+STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u)
 	{
         BIO *b;
         STACK_OF(X509_INFO) *ret;
@@ -76,13 +76,13 @@
                 return(0);
 		}
         BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_X509_INFO_read_bio(b,sk,cb);
+        ret=PEM_X509_INFO_read_bio(b,sk,cb,u);
         BIO_free(b);
         return(ret);
 	}
 #endif
 
-STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb)
+STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u)
 	{
 	X509_INFO *xi=NULL;
 	char *name=NULL,*header=NULL,**pp;
@@ -205,7 +205,7 @@
 
 				if (!PEM_get_EVP_CIPHER_INFO(header,&cipher))
 					goto err;
-				if (!PEM_do_header(&cipher,data,&len,cb))
+				if (!PEM_do_header(&cipher,data,&len,cb,u))
 					goto err;
 				p=data;
 				if (d2i(pp,&p,len) == NULL)
@@ -266,7 +266,7 @@
 
 /* A TJH addition */
 int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
-	     unsigned char *kstr, int klen, pem_password_cb *cb)
+	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
 	{
 	EVP_CIPHER_CTX ctx;
 	int i,ret=0;
@@ -328,7 +328,7 @@
 			/* normal optionally encrypted stuff */
 			if (PEM_write_bio_RSAPrivateKey(bp,
 				xi->x_pkey->dec_pkey->pkey.rsa,
-				enc,kstr,klen,cb)<=0)
+				enc,kstr,klen,cb,u)<=0)
 				goto err;
 #endif
 			}
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index ee6eba5..90f0201 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -73,10 +73,10 @@
 
 #define MIN_LENGTH	4
 
-static int def_callback(char *buf, int num, int w);
+static int def_callback(char *buf, int num, int w, void *userdata);
 static int load_iv(unsigned char **fromp,unsigned char *to, int num);
 
-static int def_callback(char *buf, int num, int w)
+static int def_callback(char *buf, int num, int w, void *userdata)
 	{
 #ifdef NO_FP_API
 	/* We should not ever call the default callback routine from
@@ -151,7 +151,7 @@
 
 #ifndef NO_FP_API
 char *PEM_ASN1_read(char *(*d2i)(), const char *name, FILE *fp, char **x,
-	     pem_password_cb *cb)
+	     pem_password_cb *cb, void *u)
 	{
         BIO *b;
         char *ret;
@@ -162,14 +162,14 @@
                 return(0);
 		}
         BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_ASN1_read_bio(d2i,name,b,x,cb);
+        ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u);
         BIO_free(b);
         return(ret);
 	}
 #endif
 
 char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp, char **x,
-	     pem_password_cb *cb)
+	     pem_password_cb *cb, void *u)
 	{
 	EVP_CIPHER_INFO cipher;
 	char *nm=NULL,*header=NULL;
@@ -200,7 +200,7 @@
 		Free(data);
 		}
 	if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err;
-	if (!PEM_do_header(&cipher,data,&len,cb)) goto err;
+	if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err;
 	p=data;
 	if (strcmp(name,PEM_STRING_EVP_PKEY) == 0) {
 		if (strcmp(nm,PEM_STRING_RSA) == 0)
@@ -220,8 +220,8 @@
 			char psbuf[PEM_BUFSIZE];
 			p8 = d2i_X509_SIG((X509_SIG **)x, &p, len);
 			if(!p8) goto p8err;
-			if (cb) klen=cb(psbuf,PEM_BUFSIZE,0);
-			else klen=def_callback(psbuf,PEM_BUFSIZE,0);
+			if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u);
+			else klen=def_callback(psbuf,PEM_BUFSIZE,0,u);
 			if (klen <= 0) {
 				PEMerr(PEM_F_PEM_ASN1_READ_BIO,
 						PEM_R_BAD_PASSWORD_READ);
@@ -247,7 +247,7 @@
 #ifndef NO_FP_API
 int PEM_ASN1_write(int (*i2d)(), const char *name, FILE *fp, char *x,
 	     const EVP_CIPHER *enc, unsigned char *kstr, int klen,
-	     pem_password_cb *callback)
+	     pem_password_cb *callback, void *u)
         {
         BIO *b;
         int ret;
@@ -258,7 +258,7 @@
                 return(0);
 		}
         BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback);
+        ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u);
         BIO_free(b);
         return(ret);
         }
@@ -266,7 +266,7 @@
 
 int PEM_ASN1_write_bio(int (*i2d)(), const char *name, BIO *bp, char *x,
 	     const EVP_CIPHER *enc, unsigned char *kstr, int klen,
-	     pem_password_cb *callback)
+	     pem_password_cb *callback, void *u)
 	{
 	EVP_CIPHER_CTX ctx;
 	int dsize=0,i,j,ret=0;
@@ -307,9 +307,9 @@
 		if (kstr == NULL)
 			{
 			if (callback == NULL)
-				klen=def_callback(buf,PEM_BUFSIZE,1);
+				klen=def_callback(buf,PEM_BUFSIZE,1,u);
 			else
-				klen=(*callback)(buf,PEM_BUFSIZE,1);
+				klen=(*callback)(buf,PEM_BUFSIZE,1,u);
 			if (klen <= 0)
 				{
 				PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY);
@@ -358,7 +358,7 @@
 	}
 
 int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
-	     pem_password_cb *callback)
+	     pem_password_cb *callback,void *u)
 	{
 	int i,j,o,klen;
 	long len;
@@ -370,9 +370,9 @@
 
 	if (cipher->cipher == NULL) return(1);
 	if (callback == NULL)
-		klen=def_callback(buf,PEM_BUFSIZE,0);
+		klen=def_callback(buf,PEM_BUFSIZE,0,u);
 	else
-		klen=callback(buf,PEM_BUFSIZE,0);
+		klen=callback(buf,PEM_BUFSIZE,0,u);
 	if (klen <= 0)
 		{
 		PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ);
@@ -751,7 +751,7 @@
 
 int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
 				  char *kstr, int klen,
-				  pem_password_cb *cb)
+				  pem_password_cb *cb, void *u)
 {
 	X509_SIG *p8;
 	PKCS8_PRIV_KEY_INFO *p8inf;
@@ -764,8 +764,8 @@
 	}
 	if(enc) {
 		if(!kstr) {
-			if(!cb) klen = def_callback(buf, PEM_BUFSIZE, 1);
-			else klen = cb(buf, PEM_BUFSIZE, 1);
+			if(!cb) klen = def_callback(buf, PEM_BUFSIZE, 1, u);
+			else klen = cb(buf, PEM_BUFSIZE, 1, u);
 			if(klen <= 0) {
 				PEMerr(PEM_F_PEM_WRITE_BIO_PKCS8PRIVATEKEY,
 								PEM_R_READ_KEY);
@@ -789,7 +789,7 @@
 }
 
 int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
-			      char *kstr, int klen, pem_password_cb *cb)
+			      char *kstr, int klen, pem_password_cb *cb, void *u)
 {
 	BIO *bp;
 	int ret;
@@ -797,7 +797,7 @@
 		PEMerr(PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY,ERR_R_BUF_LIB);
                 return(0);
 	}
-	ret = PEM_write_bio_PKCS8PrivateKey(bp, x, enc, kstr, klen, cb);
+	ret = PEM_write_bio_PKCS8PrivateKey(bp, x, enc, kstr, klen, cb, u);
 	BIO_free(bp);
 	return ret;
 }
diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c
index 8b2d591..00ee5e8 100644
--- a/crypto/x509/by_file.c
+++ b/crypto/x509/by_file.c
@@ -149,7 +149,7 @@
 		{
 		for (;;)
 			{
-			x=PEM_read_bio_X509(in,NULL,NULL);
+			x=PEM_read_bio_X509(in,NULL,NULL,NULL);
 			if (x == NULL)
 				{
 				if ((ERR_GET_REASON(ERR_peek_error()) ==
@@ -216,7 +216,7 @@
 		{
 		for (;;)
 			{
-			x=PEM_read_bio_X509_CRL(in,NULL,NULL);
+			x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
 			if (x == NULL)
 				{
 				if ((ERR_GET_REASON(ERR_peek_error()) ==
diff --git a/ssl/ssl.h b/ssl/ssl.h
index e447854..d4dcf4f 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -427,6 +427,9 @@
 	/* Default password callback. */
 /**/	pem_password_cb *default_passwd_callback;
 
+	/* Default password callback user data. */
+/**/	void *default_passwd_callback_userdata;
+
 	/* get client cert callback */
 /**/	int (*client_cert_cb)(/* SSL *ssl, X509 **x509, EVP_PKEY **pkey */);
 
@@ -727,16 +730,16 @@
 	(bp),(unsigned char **)(s_id))
 #define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio(i2d_SSL_SESSION, \
 	bp,(unsigned char *)s_id)
-#define PEM_read_SSL_SESSION(fp,x,cb) (SSL_SESSION *)PEM_ASN1_read( \
-	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb)
-#define PEM_read_bio_SSL_SESSION(bp,x,cb) (SSL_SESSION *)PEM_ASN1_read_bio( \
-	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb)
+#define PEM_read_SSL_SESSION(fp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,fp,(char **)x,cb,u)
+#define PEM_read_bio_SSL_SESSION(bp,x,cb,u) (SSL_SESSION *)PEM_ASN1_read_bio( \
+	(char *(*)())d2i_SSL_SESSION,PEM_STRING_SSL_SESSION,bp,(char **)x,cb,u)
 #define PEM_write_SSL_SESSION(fp,x) \
 	PEM_ASN1_write((int (*)())i2d_SSL_SESSION, \
-		PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL)
+		PEM_STRING_SSL_SESSION,fp, (char *)x, NULL,NULL,0,NULL,NULL)
 #define PEM_write_bio_SSL_SESSION(bp,x) \
 	PEM_ASN1_write_bio((int (*)())i2d_SSL_SESSION, \
-		PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL)
+		PEM_STRING_SSL_SESSION,bp, (char *)x, NULL,NULL,0,NULL,NULL)
 #endif
 
 #define SSL_AD_REASON_OFFSET		1000
@@ -979,7 +982,8 @@
 int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
 int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d);
 
-void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *);
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
 
 int SSL_CTX_check_private_key(SSL_CTX *ctx);
 int SSL_check_private_key(SSL *ctx);
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index ec2eb61..19ade2f 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -571,7 +571,7 @@
 
 	for (;;)
 		{
-		if (PEM_read_bio_X509(in,&x,NULL) == NULL)
+		if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
 			break;
 		if ((xn=X509_get_subject_name(x)) == NULL) goto err;
 		/* check for duplicates */
@@ -632,7 +632,7 @@
 
     for (;;)
 	{
-	if (PEM_read_bio_X509(in,&x,NULL) == NULL)
+	if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
 	    break;
 	if ((xn=X509_get_subject_name(x)) == NULL) goto err;
 	xn=X509_NAME_dup(xn);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 89c5481..365b3ce 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1032,6 +1032,7 @@
 		goto err;
 
 	ret->default_passwd_callback=NULL;
+	ret->default_passwd_callback_userdata=NULL;
 	ret->client_cert_cb=NULL;
 
 	ret->sessions=lh_new(SSL_SESSION_hash,SSL_SESSION_cmp);
@@ -1131,6 +1132,11 @@
 	ctx->default_passwd_callback=cb;
 	}
 
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u)
+	{
+	ctx->default_passwd_callback_userdata=u;
+	}
+
 void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,int (*cb)(),char *arg)
 	{
 	ctx->app_verify_callback=cb;
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index fcd4248..f367d39 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -109,7 +109,7 @@
 	else if (type == SSL_FILETYPE_PEM)
 		{
 		j=ERR_R_PEM_LIB;
-		x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback);
+		x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata);
 		}
 	else
 		{
@@ -280,7 +280,7 @@
 		{
 		j=ERR_R_PEM_LIB;
 		rsa=PEM_read_bio_RSAPrivateKey(in,NULL,
-			ssl->ctx->default_passwd_callback);
+			ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata);
 		}
 	else
 		{
@@ -360,7 +360,7 @@
 		{
 		j=ERR_R_PEM_LIB;
 		pkey=PEM_read_bio_PrivateKey(in,NULL,
-			ssl->ctx->default_passwd_callback);
+			ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata);
 		}
 	else
 		{
@@ -521,7 +521,7 @@
 	else if (type == SSL_FILETYPE_PEM)
 		{
 		j=ERR_R_PEM_LIB;
-		x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback);
+		x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
 		}
 	else
 		{
@@ -618,7 +618,7 @@
 		{
 		j=ERR_R_PEM_LIB;
 		rsa=PEM_read_bio_RSAPrivateKey(in,NULL,
-			ctx->default_passwd_callback);
+			ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
 		}
 	else
 		{
@@ -695,7 +695,7 @@
 		{
 		j=ERR_R_PEM_LIB;
 		pkey=PEM_read_bio_PrivateKey(in,NULL,
-			ctx->default_passwd_callback);
+			ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
 		}
 	else
 		{
@@ -759,7 +759,7 @@
 		goto end;
 		}
 
-	x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback);
+	x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata);
 	if (x == NULL)
 		{
 		SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB);
@@ -784,7 +784,7 @@
 			ctx->extra_certs = NULL;
 			}
 
-		while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback))
+		while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata))
 			!= NULL)
 			{
 			r = SSL_CTX_add_extra_chain_cert(ctx, ca);
diff --git a/util/ssleay.num b/util/ssleay.num
index d86c140..8121738 100755
--- a/util/ssleay.num
+++ b/util/ssleay.num
@@ -214,3 +214,4 @@
 SSL_CTX_set_cert_verify_callback        232
 sk_SSL_COMP_sort                        233
 sk_SSL_CIPHER_sort                      234
+SSL_CTX_set_default_passwd_cb_userdata  235