Make the necessary changes to work with the recent "ex_data" overhaul.
See the commit log message for that for more information.

NB: X509_STORE_CTX's use of "ex_data" support was actually misimplemented
(initialisation by "memset" won't/can't/doesn't work). This fixes that but
requires that X509_STORE_CTX_init() be able to handle errors - so its
prototype has been changed to return 'int' rather than 'void'. All uses of
that function throughout the source code have been tracked down and
adjusted.
diff --git a/apps/Makefile.ssl b/apps/Makefile.ssl
index bce72a9..a2c23a3 100644
--- a/apps/Makefile.ssl
+++ b/apps/Makefile.ssl
@@ -772,8 +772,8 @@
 speed.o: ../include/openssl/sha.h ../include/openssl/stack.h
 speed.o: ../include/openssl/symhacks.h ../include/openssl/txt_db.h
 speed.o: ../include/openssl/types.h ../include/openssl/ui.h
-speed.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ./testdsa.h
-speed.o: ./testrsa.h apps.h speed.c
+speed.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h apps.h speed.c
+speed.o: testdsa.h testrsa.h
 spkac.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
 spkac.o: ../include/openssl/bn.h ../include/openssl/buffer.h
 spkac.o: ../include/openssl/conf.h ../include/openssl/crypto.h
diff --git a/apps/apps.h b/apps/apps.h
index de136f4..869b13d 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -140,7 +140,7 @@
 		ENGINE_load_builtin_engines(); setup_ui_method(); } while(0)
 #  endif
 #  define apps_shutdown() \
-		destroy_ui_method()
+		do { destroy_ui_method(); CRYPTO_cleanup_all_ex_data(); } while(0)
 #endif
 
 typedef struct args_st
diff --git a/apps/crl.c b/apps/crl.c
index 82ef8ce..5ea59d0 100644
--- a/apps/crl.c
+++ b/apps/crl.c
@@ -235,7 +235,11 @@
 			X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
 		ERR_clear_error();
 
-		X509_STORE_CTX_init(&ctx, store, NULL, NULL);
+		if(!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) {
+			BIO_printf(bio_err,
+				"Error initialising X509 store\n");
+			goto end;
+		}
 
 		i = X509_STORE_get_by_subject(&ctx, X509_LU_X509, 
 					X509_CRL_get_issuer(x), &xobj);
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index b507491..d90cf59 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -810,6 +810,9 @@
 	STACK_OF(X509) *chn;
 	int i;
 
+	/* FIXME: Should really check the return status of X509_STORE_CTX_init
+	 * for an error, but how that fits into the return value of this
+	 * function is less obvious. */
 	X509_STORE_CTX_init(&store_ctx, store, cert, NULL);
 	if (X509_verify_cert(&store_ctx) <= 0) {
 		i = X509_STORE_CTX_get_error (&store_ctx);
diff --git a/apps/verify.c b/apps/verify.c
index 60da5c5..b1a4dac 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -249,7 +249,11 @@
 		goto end;
 		}
 	X509_STORE_set_flags(ctx, vflags);
-	X509_STORE_CTX_init(csc,ctx,x,uchain);
+	if(!X509_STORE_CTX_init(csc,ctx,x,uchain))
+		{
+		ERR_print_errors(bio_err);
+		goto end;
+		}
 	if(tchain) X509_STORE_CTX_trusted_stack(csc, tchain);
 	if(purpose >= 0) X509_STORE_CTX_set_purpose(csc, purpose);
 	i=X509_verify_cert(csc);
diff --git a/apps/x509.c b/apps/x509.c
index f18aaf5..65b072c 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -1128,7 +1128,11 @@
 	EVP_PKEY_copy_parameters(upkey,pkey);
 	EVP_PKEY_free(upkey);
 
-	X509_STORE_CTX_init(&xsc,ctx,x,NULL);
+	if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
+		{
+		BIO_printf(bio_err,"Error initialising X509 store\n");
+		goto end;
+		}
 	if (sno) bs = sno;
 	else if (!(bs = load_serial(CAfile, serialfile, create)))
 		goto end;
diff --git a/crypto/asn1/x_x509.c b/crypto/asn1/x_x509.c
index b0d859d..b50167c 100644
--- a/crypto/asn1/x_x509.c
+++ b/crypto/asn1/x_x509.c
@@ -63,9 +63,6 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
-static int x509_meth_num = 0;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_meth = NULL;
-
 ASN1_SEQUENCE(X509_CINF) = {
 	ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
 	ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
@@ -96,7 +93,7 @@
 		ret->skid = NULL;
 		ret->akid = NULL;
 		ret->aux = NULL;
-		CRYPTO_new_ex_data(x509_meth, ret, &ret->ex_data);
+		CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
 		break;
 
 		case ASN1_OP_D2I_POST:
@@ -105,7 +102,7 @@
 		break;
 
 		case ASN1_OP_FREE_POST:
-		CRYPTO_free_ex_data(x509_meth,ret,&ret->ex_data);
+		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
 		X509_CERT_AUX_free(ret->aux);
 		ASN1_OCTET_STRING_free(ret->skid);
 		AUTHORITY_KEYID_free(ret->akid);
@@ -142,10 +139,8 @@
 int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
         {
-	if(CRYPTO_get_ex_new_index(x509_meth_num, &x509_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (x509_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, argl, argp,
+				new_func, dup_func, free_func);
         }
 
 int X509_set_ex_data(X509 *r, int idx, void *arg)
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
index dcf0338..50df223 100644
--- a/crypto/bio/bio_lib.c
+++ b/crypto/bio/bio_lib.c
@@ -63,9 +63,6 @@
 #include <openssl/bio.h>
 #include <openssl/stack.h>
 
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *bio_meth=NULL;
-static int bio_meth_num=0;
-
 BIO *BIO_new(BIO_METHOD *method)
 	{
 	BIO *ret=NULL;
@@ -100,10 +97,14 @@
 	bio->references=1;
 	bio->num_read=0L;
 	bio->num_write=0L;
-	CRYPTO_new_ex_data(bio_meth,bio,&bio->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
 	if (method->create != NULL)
 		if (!method->create(bio))
+			{
+			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
+					&bio->ex_data);
 			return(0);
+			}
 	return(1);
 	}
 
@@ -129,7 +130,7 @@
 		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
 			return(i);
 
-	CRYPTO_free_ex_data(bio_meth,a,&a->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
 
 	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
 	ret=a->method->destroy(a);
@@ -482,7 +483,8 @@
 			}
 
 		/* copy app data */
-		if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data))
+		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data,
+					&bio->ex_data))
 			goto err;
 
 		if (ret == NULL)
@@ -512,10 +514,8 @@
 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
-	if(CRYPTO_get_ex_new_index(bio_meth_num, &bio_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (bio_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
+				new_func, dup_func, free_func);
 	}
 
 int BIO_set_ex_data(BIO *bio, int idx, void *data)
diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c
index f96b454..7c30461 100644
--- a/crypto/dh/dh_lib.c
+++ b/crypto/dh/dh_lib.c
@@ -65,8 +65,6 @@
 const char *DH_version="Diffie-Hellman" OPENSSL_VERSION_PTEXT;
 
 static const DH_METHOD *default_DH_method = NULL;
-static int dh_meth_num = 0;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *dh_meth = NULL;
 
 void DH_set_default_openssl_method(const DH_METHOD *meth)
 {
@@ -174,10 +172,10 @@
 	ret->method_mont_p=NULL;
 	ret->references = 1;
 	ret->flags=meth->flags;
-	CRYPTO_new_ex_data(dh_meth,ret,&ret->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
 	if ((meth->init != NULL) && !meth->init(ret))
 		{
-		CRYPTO_free_ex_data(dh_meth,ret,&ret->ex_data);
+		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
 		OPENSSL_free(ret);
 		ret=NULL;
 		}
@@ -206,7 +204,7 @@
 	if(meth->finish) meth->finish(r);
 	ENGINE_finish(r->engine);
 
-	CRYPTO_free_ex_data(dh_meth, r, &r->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
 
 	if (r->p != NULL) BN_clear_free(r->p);
 	if (r->g != NULL) BN_clear_free(r->g);
@@ -238,10 +236,8 @@
 int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
         {
-	if(CRYPTO_get_ex_new_index(dh_meth_num, &dh_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (dh_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, argl, argp,
+				new_func, dup_func, free_func);
         }
 
 int DH_set_ex_data(DH *d, int idx, void *arg)
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
index 98878df..bae39c2 100644
--- a/crypto/dsa/dsa_lib.c
+++ b/crypto/dsa/dsa_lib.c
@@ -68,8 +68,6 @@
 const char *DSA_version="DSA" OPENSSL_VERSION_PTEXT;
 
 static const DSA_METHOD *default_DSA_method = NULL;
-static int dsa_meth_num = 0;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *dsa_meth = NULL;
 
 void DSA_set_default_openssl_method(const DSA_METHOD *meth)
 {
@@ -181,10 +179,10 @@
 
 	ret->references=1;
 	ret->flags=meth->flags;
-	CRYPTO_new_ex_data(dsa_meth,ret,&ret->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
 	if ((meth->init != NULL) && !meth->init(ret))
 		{
-		CRYPTO_free_ex_data(dsa_meth,ret,&ret->ex_data);
+		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, ret, &ret->ex_data);
 		OPENSSL_free(ret);
 		ret=NULL;
 		}
@@ -216,7 +214,7 @@
 	if(meth->finish) meth->finish(r);
 	ENGINE_finish(r->engine);
 
-	CRYPTO_free_ex_data(dsa_meth, r, &r->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
 
 	if (r->p != NULL) BN_clear_free(r->p);
 	if (r->q != NULL) BN_clear_free(r->q);
@@ -266,10 +264,8 @@
 int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
         {
-	if(CRYPTO_get_ex_new_index(dsa_meth_num, &dsa_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (dsa_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp,
+				new_func, dup_func, free_func);
         }
 
 int DSA_set_ex_data(DSA *d, int idx, void *arg)
diff --git a/crypto/dsa/dsatest.c b/crypto/dsa/dsatest.c
index 9eea866..5f24b59 100644
--- a/crypto/dsa/dsatest.c
+++ b/crypto/dsa/dsatest.c
@@ -202,6 +202,7 @@
 	if (!ret)
 		ERR_print_errors(bio_err);
 	if (dsa != NULL) DSA_free(dsa);
+	CRYPTO_cleanup_all_ex_data();
 	ERR_remove_state(0);
 	CRYPTO_mem_leaks(bio_err);
 	if (bio_err != NULL)
diff --git a/crypto/ec/ectest.c b/crypto/ec/ectest.c
index c1f0b44..1d0b337 100644
--- a/crypto/ec/ectest.c
+++ b/crypto/ec/ectest.c
@@ -619,6 +619,7 @@
 	if (P_521) EC_GROUP_free(P_521);
 
 	ENGINE_cleanup();
+	CRYPTO_cleanup_all_ex_data();
 	ERR_free_strings();
 	ERR_remove_state(0);
 	CRYPTO_mem_leaks_fp(stderr);
diff --git a/crypto/engine/engine_list.c b/crypto/engine/engine_list.c
index 53eadbb..926ff5a 100644
--- a/crypto/engine/engine_list.c
+++ b/crypto/engine/engine_list.c
@@ -61,14 +61,6 @@
 #include "engine_int.h"
 #include <openssl/engine.h>
 
-/* Weird "ex_data" handling. Some have suggested there's some problems with the
- * CRYPTO_EX_DATA code (or model), but for now I'm implementing it exactly as
- * it's done in crypto/rsa/. That way the usage and documentation of that can be
- * used to assist here, and any changes or fixes made there should similarly map
- * over here quite straightforwardly. */
-static int engine_ex_data_num = 0;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *engine_ex_data_stack = NULL;
-
 /* The linked-list of pointers to engine types. engine_list_head
  * incorporates an implicit structural reference but engine_list_tail
  * does not - the latter is a computational niceity and only points
@@ -85,7 +77,7 @@
  * is needed because the engine list may genuinely become empty during
  * use (so we can't use engine_list_head as an indicator for example. */
 static int engine_list_flag = 0;
-static int ENGINE_free_nolock(ENGINE *e);
+static int ENGINE_free_util(ENGINE *e, int locked);
 
 /* These static functions starting with a lower case "engine_" always
  * take place when CRYPTO_LOCK_ENGINE has been locked up. */
@@ -177,7 +169,7 @@
 		engine_list_head = e->next;
 	if(engine_list_tail == e)
 		engine_list_tail = e->prev;
-	ENGINE_free_nolock(e);
+	ENGINE_free_util(e, 0);
 	return 1;
 	}
 
@@ -199,7 +191,7 @@
 		toret = 0;
 	else
 		engine_list_flag = 1;
-	ENGINE_free_nolock(def_engine);
+	ENGINE_free_util(def_engine, 0);
 	return 1;
 	}
 
@@ -393,11 +385,11 @@
 	memset(ret, 0, sizeof(ENGINE));
 	ret->struct_ref = 1;
 	engine_ref_debug(ret, 0, 1)
-	CRYPTO_new_ex_data(engine_ex_data_stack, ret, &ret->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data);
 	return ret;
 	}
 
-int ENGINE_free(ENGINE *e)
+static int ENGINE_free_util(ENGINE *e, int locked)
 	{
 	int i;
 
@@ -407,7 +399,10 @@
 			ERR_R_PASSED_NULL_PARAMETER);
 		return 0;
 		}
-	i = CRYPTO_add(&e->struct_ref,-1,CRYPTO_LOCK_ENGINE);
+	if(locked)
+		i = CRYPTO_add(&e->struct_ref,-1,CRYPTO_LOCK_ENGINE);
+	else
+		i = --e->struct_ref;
 	engine_ref_debug(e, 0, -1)
 	if (i > 0) return 1;
 #ifdef REF_CHECK
@@ -418,44 +413,21 @@
 		}
 #endif
 	sk_ENGINE_EVP_CIPHER_pop_free(e->ciphers,ENGINE_free_engine_cipher);
-	CRYPTO_free_ex_data(engine_ex_data_stack, e, &e->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data);
 	OPENSSL_free(e);
 	return 1;
 	}
 
-static int ENGINE_free_nolock(ENGINE *e)
+int ENGINE_free(ENGINE *e)
 	{
-	int i;
-
-	if(e == NULL)
-		{
-		ENGINEerr(ENGINE_F_ENGINE_FREE,
-			ERR_R_PASSED_NULL_PARAMETER);
-		return 0;
-		}
-	
-	i=--e->struct_ref;
-	engine_ref_debug(e, 0, -1)
-	if (i > 0) return 1;
-#ifdef REF_CHECK
-	if (i < 0)
-		{
-		fprintf(stderr,"ENGINE_free, bad structural reference count\n");
-		abort();
-		}
-#endif
-	CRYPTO_free_ex_data(engine_ex_data_stack, e, &e->ex_data);
-	OPENSSL_free(e);
-	return 1;
+	return ENGINE_free_util(e, 1);
 	}
 
 int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 		CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
-	if(CRYPTO_get_ex_new_index(engine_ex_data_num, &engine_ex_data_stack,
-			argl, argp, new_func, dup_func, free_func) < 0)
-		return -1;
-	return (engine_ex_data_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ENGINE, argl, argp,
+			new_func, dup_func, free_func);
 	}
 
 int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg)
diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
index 43b62a8..1f5fda7 100644
--- a/crypto/ocsp/ocsp_vfy.c
+++ b/crypto/ocsp/ocsp_vfy.c
@@ -101,10 +101,16 @@
 		}
 	if (!(flags & OCSP_NOVERIFY))
 		{
+		int init_res;
 		if(flags & OCSP_NOCHAIN)
-			X509_STORE_CTX_init(&ctx, st, signer, NULL);
+			init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL);
 		else
-			X509_STORE_CTX_init(&ctx, st, signer, bs->certs);
+			init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs);
+		if(!init_res)
+			{
+			OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB);
+			goto end;
+			}
 
 		X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
 		ret = X509_verify_cert(&ctx);
@@ -389,10 +395,17 @@
 		}
 	if (!(flags & OCSP_NOVERIFY))
 		{
+		int init_res;
 		if(flags & OCSP_NOCHAIN)
-			X509_STORE_CTX_init(&ctx, store, signer, NULL);
+			init_res = X509_STORE_CTX_init(&ctx, store, signer, NULL);
 		else
-			X509_STORE_CTX_init(&ctx, store, signer, req->optionalSignature->certs);
+			init_res = X509_STORE_CTX_init(&ctx, store, signer,
+					req->optionalSignature->certs);
+		if(!init_res)
+			{
+			OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,ERR_R_X509_LIB);
+			return 0;
+			}
 
 		X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
 		X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST);
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
index e2c82a2..4ff021e 100644
--- a/crypto/pkcs7/pk7_doit.c
+++ b/crypto/pkcs7/pk7_doit.c
@@ -663,7 +663,11 @@
 		}
 
 	/* Lets verify */
-	X509_STORE_CTX_init(ctx,cert_store,x509,cert);
+	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
+		{
+		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
+		goto err;
+		}
 	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
 	i=X509_verify_cert(ctx);
 	if (i <= 0) 
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
index 348ec1d..f0d071e 100644
--- a/crypto/pkcs7/pk7_smime.c
+++ b/crypto/pkcs7/pk7_smime.c
@@ -201,11 +201,20 @@
 	if (!(flags & PKCS7_NOVERIFY)) for (k = 0; k < sk_X509_num(signers); k++) {
 		signer = sk_X509_value (signers, k);
 		if (!(flags & PKCS7_NOCHAIN)) {
-			X509_STORE_CTX_init(&cert_ctx, store, signer,
-							p7->d.sign->cert);
+			if(!X509_STORE_CTX_init(&cert_ctx, store, signer,
+							p7->d.sign->cert))
+				{
+				PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB);
+				sk_X509_free(signers);
+				return 0;
+				}
 			X509_STORE_CTX_set_purpose(&cert_ctx,
 						X509_PURPOSE_SMIME_SIGN);
-		} else X509_STORE_CTX_init (&cert_ctx, store, signer, NULL);
+		} else if(!X509_STORE_CTX_init (&cert_ctx, store, signer, NULL)) {
+			PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB);
+			sk_X509_free(signers);
+			return 0;
+		}
 		i = X509_verify_cert(&cert_ctx);
 		if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx);
 		X509_STORE_CTX_cleanup(&cert_ctx);
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index 3accf01..e3368c1 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -67,8 +67,6 @@
 const char *RSA_version="RSA" OPENSSL_VERSION_PTEXT;
 
 static const RSA_METHOD *default_RSA_meth=NULL;
-static int rsa_meth_num=0;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *rsa_meth=NULL;
 
 RSA *RSA_new(void)
 	{
@@ -198,10 +196,10 @@
 	ret->blinding=NULL;
 	ret->bignum_data=NULL;
 	ret->flags=meth->flags;
-	CRYPTO_new_ex_data(rsa_meth,ret,&ret->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
 	if ((meth->init != NULL) && !meth->init(ret))
 		{
-		CRYPTO_free_ex_data(rsa_meth, ret, &ret->ex_data);
+		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
 		OPENSSL_free(ret);
 		ret=NULL;
 		}
@@ -233,7 +231,7 @@
 		meth->finish(r);
 	ENGINE_finish(r->engine);
 
-	CRYPTO_free_ex_data(rsa_meth,r,&r->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
 
 	if (r->n != NULL) BN_clear_free(r->n);
 	if (r->e != NULL) BN_clear_free(r->e);
@@ -267,10 +265,8 @@
 int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
         {
-	if(CRYPTO_get_ex_new_index(rsa_meth_num, &rsa_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (rsa_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp,
+				new_func, dup_func, free_func);
         }
 
 int RSA_set_ex_data(RSA *r, int idx, void *arg)
diff --git a/crypto/rsa/rsa_test.c b/crypto/rsa/rsa_test.c
index 2c0a1d5..5dee24b 100644
--- a/crypto/rsa/rsa_test.c
+++ b/crypto/rsa/rsa_test.c
@@ -307,6 +307,7 @@
 	RSA_free(key);
 	}
 
+    CRYPTO_cleanup_all_ex_data();
     ERR_remove_state(0);
 
     CRYPTO_mem_leaks_fp(stdout);
diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c
index c526426..16946ca 100644
--- a/crypto/ui/ui_lib.c
+++ b/crypto/ui/ui_lib.c
@@ -66,8 +66,6 @@
 IMPLEMENT_STACK_OF(UI_STRING_ST)
 
 static const UI_METHOD *default_UI_meth=NULL;
-static int ui_meth_num=0;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ui_meth=NULL;
 
 UI *UI_new(void)
 	{
@@ -91,7 +89,7 @@
 
 	ret->strings=NULL;
 	ret->user_data=NULL;
-	CRYPTO_new_ex_data(ui_meth,ret,&ret->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data);
 	return ret;
 	}
 
@@ -119,6 +117,7 @@
 	if (ui == NULL)
 		return;
 	sk_UI_STRING_pop_free(ui->strings,free_string);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
 	OPENSSL_free(ui);
 	}
 
@@ -574,10 +573,8 @@
 int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
         {
-	if(CRYPTO_get_ex_new_index(ui_meth_num, &ui_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (ui_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp,
+				new_func, dup_func, free_func);
         }
 
 int UI_set_ex_data(UI *r, int idx, void *arg)
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 2d0ecf2..f1040ac 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -1221,6 +1221,8 @@
 #define X509_F_X509_REQ_TO_X509				 123
 #define X509_F_X509_STORE_ADD_CERT			 124
 #define X509_F_X509_STORE_ADD_CRL			 125
+#define X509_F_X509_STORE_CTX_INIT			 143
+#define X509_F_X509_STORE_CTX_NEW			 142
 #define X509_F_X509_STORE_CTX_PURPOSE_INHERIT		 134
 #define X509_F_X509_TO_X509_REQ				 126
 #define X509_F_X509_TRUST_ADD				 133
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index fa72c16..5bbf4ac 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -100,6 +100,8 @@
 {ERR_PACK(0,X509_F_X509_REQ_TO_X509,0),	"X509_REQ_to_X509"},
 {ERR_PACK(0,X509_F_X509_STORE_ADD_CERT,0),	"X509_STORE_add_cert"},
 {ERR_PACK(0,X509_F_X509_STORE_ADD_CRL,0),	"X509_STORE_add_crl"},
+{ERR_PACK(0,X509_F_X509_STORE_CTX_INIT,0),	"X509_STORE_CTX_init"},
+{ERR_PACK(0,X509_F_X509_STORE_CTX_NEW,0),	"X509_STORE_CTX_new"},
 {ERR_PACK(0,X509_F_X509_STORE_CTX_PURPOSE_INHERIT,0),	"X509_STORE_CTX_purpose_inherit"},
 {ERR_PACK(0,X509_F_X509_TO_X509_REQ,0),	"X509_to_X509_REQ"},
 {ERR_PACK(0,X509_F_X509_TRUST_ADD,0),	"X509_TRUST_add"},
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index a298343..b780dae 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -62,8 +62,6 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_meth=NULL;
-
 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
 	{
 	X509_LOOKUP *ret;
@@ -202,7 +200,7 @@
 	ret->cert_crl = 0;
 	ret->cleanup = 0;
 
-	memset(&ret->ex_data,0,sizeof(CRYPTO_EX_DATA));
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data);
 	ret->references=1;
 	ret->depth=0;
 	return ret;
@@ -245,7 +243,7 @@
 	sk_X509_LOOKUP_free(sk);
 	sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
 
-	CRYPTO_free_ex_data(x509_store_meth,vfy,&vfy->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
 	OPENSSL_free(vfy);
 	}
 
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 4c3aae7..892b784 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -80,9 +80,6 @@
 static int internal_verify(X509_STORE_CTX *ctx);
 const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
 
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_ctx_method=NULL;
-static int x509_store_ctx_num=0;
-
 
 static int null_callback(int ok, X509_STORE_CTX *e)
 	{
@@ -891,14 +888,9 @@
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
 	/* This function is (usually) called only once, by
-	 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c).
-	 * That function uses locking, so we don't (usually)
-	 * have to worry about locking here. For the whole cruel
-	 * truth, see crypto/ex_data.c */
-	if(CRYPTO_get_ex_new_index(x509_store_ctx_num, &x509_store_ctx_method,
-			argl, argp, new_func, dup_func, free_func) < 0)
-		return -1;
-	return (x509_store_ctx_num++);
+	 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
+			new_func, dup_func, free_func);
 	}
 
 int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
@@ -1032,7 +1024,12 @@
 {
 	X509_STORE_CTX *ctx;
 	ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
-	if (ctx) memset(ctx, 0, sizeof(X509_STORE_CTX));
+	if (!ctx)
+		{
+		X509err(X509_F_X509_STORE_CTX_NEW,ERR_R_MALLOC_FAILURE);
+		return NULL;
+		}
+	memset(ctx, 0, sizeof(X509_STORE_CTX));
 	return ctx;
 }
 
@@ -1042,7 +1039,7 @@
 	OPENSSL_free(ctx);
 }
 
-void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
 	     STACK_OF(X509) *chain)
 	{
 	ctx->ctx=store;
@@ -1111,7 +1108,18 @@
 
 	ctx->cleanup = store->cleanup;
 
-	memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA));
+	/* This memset() can't make any sense anyway, so it's removed. As
+	 * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a
+	 * corresponding "new" here and remove this bogus initialisation. */
+	/* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */
+	if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
+				&(ctx->ex_data)))
+		{
+		OPENSSL_free(ctx);
+		X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
+		return 0;
+		}
+	return 1;
 	}
 
 /* Set alternative lookup method: just a STACK of trusted certificates.
@@ -1132,7 +1140,7 @@
 		sk_X509_pop_free(ctx->chain,X509_free);
 		ctx->chain=NULL;
 		}
-	CRYPTO_free_ex_data(x509_store_ctx_method,ctx,&(ctx->ex_data));
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
 	memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
 	}
 
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index 043ed49..689062f 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -332,7 +332,7 @@
 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
 
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
-void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
 			 X509 *x509, STACK_OF(X509) *chain);
 void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index b4d1b84..68ddb14 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -272,7 +272,11 @@
 		}
 	if (x != NULL)
 		{
-		X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL);
+		if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL))
+			{
+			SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
+			return(0);
+			}
 
 		for (;;)
 			{
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index ab2e009..fcd6ff9 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -455,7 +455,11 @@
 		return(0);
 
 	x=sk_X509_value(sk,0);
-	X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk);
+	if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk))
+		{
+		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB);
+		return(0);
+		}
 	if (SSL_get_verify_depth(s) >= 0)
 		X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
 	X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index df085e6..8aec403 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -71,11 +71,6 @@
 
 const char *SSL_version_str=OPENSSL_VERSION_TEXT;
 
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_meth=NULL;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_ctx_meth=NULL;
-static int ssl_meth_num=0;
-static int ssl_ctx_meth_num=0;
-
 OPENSSL_GLOBAL SSL3_ENC_METHOD ssl3_undef_enc_method={
 	/* evil casts, but these functions are only called if there's a library bug */
 	(int (*)(SSL *,int))ssl_undefined_function,
@@ -242,7 +237,7 @@
 	s->read_ahead=ctx->read_ahead; /* used to happen in SSL_clear */
 	SSL_clear(s);
 
-	CRYPTO_new_ex_data(ssl_meth,s,&s->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
 
 	return(s);
 err:
@@ -372,7 +367,7 @@
 		}
 #endif
 
-	CRYPTO_free_ex_data(ssl_meth,(char *)s,&s->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
 
 	if (s->bbio != NULL)
 		{
@@ -1272,7 +1267,7 @@
 	if ((ret->client_CA=sk_X509_NAME_new_null()) == NULL)
 		goto err;
 
-	CRYPTO_new_ex_data(ssl_ctx_meth,(char *)ret,&ret->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data);
 
 	ret->extra_certs=NULL;
 	ret->comp_methods=SSL_COMP_get_compression_methods();
@@ -1308,7 +1303,7 @@
 		abort(); /* ok */
 		}
 #endif
-	CRYPTO_free_ex_data(ssl_ctx_meth,(char *)a,&a->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
 
 	if (a->sessions != NULL)
 		{
@@ -1806,7 +1801,7 @@
 	ret->options=s->options;
 
 	/* copy app data, a little dangerous perhaps */
-	if (!CRYPTO_dup_ex_data(ssl_meth,&ret->ex_data,&s->ex_data))
+	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, &ret->ex_data, &s->ex_data))
 		goto err;
 
 	/* setup rbio, and wbio */
@@ -2051,10 +2046,8 @@
 int SSL_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func,
 			 CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func)
 	{
-	if(CRYPTO_get_ex_new_index(ssl_meth_num, &ssl_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (ssl_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp,
+				new_func, dup_func, free_func);
 	}
 
 int SSL_set_ex_data(SSL *s,int idx,void *arg)
@@ -2070,10 +2063,8 @@
 int SSL_CTX_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func,
 			     CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func)
 	{
-	if(CRYPTO_get_ex_new_index(ssl_ctx_meth_num, &ssl_ctx_meth, argl, argp,
-				new_func, dup_func, free_func) < 0)
-		return -1;
-	return (ssl_ctx_meth_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp,
+				new_func, dup_func, free_func);
 	}
 
 int SSL_CTX_set_ex_data(SSL_CTX *s,int idx,void *arg)
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 5821792..9078d75 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -64,8 +64,6 @@
 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
 static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
-static int ssl_session_num=0;
-static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ssl_session_meth=NULL;
 
 SSL_SESSION *SSL_get_session(SSL *ssl)
 /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
@@ -91,10 +89,8 @@
 int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
 	{
-	if(CRYPTO_get_ex_new_index(ssl_session_num, &ssl_session_meth, argl,
-				argp, new_func, dup_func, free_func) < 0)
-		return -1;
-	return (ssl_session_num++);
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp,
+			new_func, dup_func, free_func);
 	}
 
 int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
@@ -126,7 +122,7 @@
 	ss->prev=NULL;
 	ss->next=NULL;
 	ss->compress_meth=0;
-	CRYPTO_new_ex_data(ssl_session_meth,ss,&ss->ex_data);
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 	return(ss);
 	}
 
@@ -520,7 +516,7 @@
 		}
 #endif
 
-	CRYPTO_free_ex_data(ssl_session_meth,ss,&ss->ex_data);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
 
 	memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH);
 	memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH);
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index 7d1249f..9ba5607 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -714,6 +714,7 @@
 	free_tmp_rsa();
 #endif
 	ENGINE_cleanup();
+	CRYPTO_cleanup_all_ex_data();
 	ERR_free_strings();
 	ERR_remove_state(0);
 	EVP_cleanup();
diff --git a/util/libeay.num b/util/libeay.num
index ee9d309..3e274c9 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -2653,3 +2653,7 @@
 DH_up                                   3102	EXIST::FUNCTION:DH
 RSA_up                                  3103	EXIST::FUNCTION:RSA
 EVP_DigestInit_dbg                      3104	EXIST::FUNCTION:
+CRYPTO_cleanup_all_ex_data              3105	EXIST::FUNCTION:
+CRYPTO_set_ex_data_implementation       3106	EXIST::FUNCTION:
+CRYPTO_ex_data_new_class                3107	EXIST::FUNCTION:
+CRYPTO_get_ex_data_implementation       3108	EXIST::FUNCTION: