Add support for certificate stores in CERT structure. This makes it
possible to have different stores per SSL structure or one store in
the parent SSL_CTX. Include distint stores for certificate chain
verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN
to build and store a certificate chain in CERT structure: returing
an error if the chain cannot be built: this will allow applications
to test if a chain is correctly configured.

Note: if the CERT based stores are not set then the parent SSL_CTX
store is used to retain compatibility with existing behaviour.
diff --git a/CHANGES b/CHANGES
index 8759585..7e9e7c5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,19 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) Add support for certificate stores in CERT structure. This makes it
+     possible to have different stores per SSL structure or one store in
+     the parent SSL_CTX. Include distint stores for certificate chain
+     verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN
+     to build and store a certificate chain in CERT structure: returing
+     an error if the chain cannot be built: this will allow applications
+     to test if a chain is correctly configured.
+
+     Note: if the CERT based stores are not set then the parent SSL_CTX
+     store is used to retain compatibility with existing behaviour.
+
+     [Steve Henson]
+
   *) New function ssl_set_client_disabled to set a ciphersuite disabled
      mask based on the current session, check mask when sending client
      hello and checking the requested ciphersuite.
diff --git a/apps/s_apps.h b/apps/s_apps.h
index c04e2d3..c7e6926 100644
--- a/apps/s_apps.h
+++ b/apps/s_apps.h
@@ -155,7 +155,7 @@
 #ifdef HEADER_SSL_H
 int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
 int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
-							STACK_OF(X509) *chain);
+					STACK_OF(X509) *chain, int build_chain);
 # ifndef OPENSSL_NO_TLSEXT
 int set_cert_key_and_authz(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
                            unsigned char *authz, size_t authz_length);
diff --git a/apps/s_cb.c b/apps/s_cb.c
index afc30f2..2ac3f96 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -251,7 +251,7 @@
 	}
 
 int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
-		       STACK_OF(X509) *chain)
+		       STACK_OF(X509) *chain, int build_chain)
 	{
 	if (cert == NULL)
 		return 1;
@@ -282,6 +282,13 @@
 		ERR_print_errors(bio_err);
 		return 0;
 		}
+	if (!chain && build_chain && !SSL_CTX_build_cert_chain(ctx, 0))
+		{
+		BIO_printf(bio_err,"error building certificate chain\n");
+		ERR_print_errors(bio_err);
+		return 0;
+		}
+		
 	return 1;
 	}
 
@@ -1123,6 +1130,7 @@
 	X509 *cert;
 	EVP_PKEY *key;
 	STACK_OF(X509) *chain;
+	int build_chain;
 	struct ssl_excert_st *next, *prev;
 	};
 
@@ -1150,7 +1158,16 @@
 			{
 			SSL_use_certificate(ssl, exc->cert);
 			SSL_use_PrivateKey(ssl, exc->key);
-			if (exc->chain)
+			/* NB: we wouldn't normally do this as it is
+			 * not efficient building chains on each connection
+			 * better to cache the chain in advance.
+			 */
+			if (exc->build_chain)
+				{
+				if (!SSL_build_cert_chain(ssl, 0))
+					return 0;
+				}
+			else if (exc->chain)
 				SSL_set1_chain(ssl, exc->chain);
 			}
 		exc = exc->prev;
@@ -1176,6 +1193,7 @@
 	exc->key = NULL;
 	exc->chain = NULL;
 	exc->prev = NULL;
+	exc->build_chain = 0;
 
 	exc->next = *pexc;
 	*pexc = exc;
@@ -1260,6 +1278,7 @@
 	{
 	char *arg = **pargs, *argn = (*pargs)[1];
 	SSL_EXCERT *exc = *pexc;
+	int narg = 2;
 	if (!exc)
 		{
 		if (ssl_excert_prepend(&exc))
@@ -1316,6 +1335,11 @@
 			}
 		exc->chainfile = argn;
 		}
+	else if (strcmp(arg,"-xchain_build") == 0)
+		{
+		narg = 1;
+		exc->build_chain = 1;
+		}
 	else if (strcmp(arg,"-xcertform") == 0)
 		{
 		if (!argn)
@@ -1337,10 +1361,10 @@
 	else
 		return 0;
 
-	(*pargs) += 2;
+	(*pargs) += narg;
 
 	if (pargc)
-		*pargc -= 2;
+		*pargc -= narg;
 
 	*pexc = exc;
 
diff --git a/apps/s_client.c b/apps/s_client.c
index 97f7cbd..783a49e 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -559,6 +559,7 @@
 	{
 	unsigned int off=0, clr=0;
 	unsigned int cert_flags=0;
+	int build_chain = 0;
 	SSL *con=NULL;
 #ifndef OPENSSL_NO_KRB5
 	KSSL_CTX *kctx;
@@ -877,6 +878,8 @@
 			if (--argc < 1) goto bad;
 			CApath= *(++argv);
 			}
+		else if	(strcmp(*argv,"-build_chain") == 0)
+			build_chain = 1;
 		else if	(strcmp(*argv,"-CAfile") == 0)
 			{
 			if (--argc < 1) goto bad;
@@ -1212,8 +1215,6 @@
 #endif
 
 	SSL_CTX_set_verify(ctx,verify,verify_callback);
-	if (!set_cert_key_stuff(ctx,cert,key, NULL))
-		goto end;
 
 	if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
 		(!SSL_CTX_set_default_verify_paths(ctx)))
@@ -1223,6 +1224,9 @@
 		/* goto end; */
 		}
 
+	if (!set_cert_key_stuff(ctx,cert,key, NULL, build_chain))
+		goto end;
+
 #ifndef OPENSSL_NO_TLSEXT
 	if (curves != NULL)
 		if(!SSL_CTX_set1_curves_list(ctx,curves)) {
diff --git a/apps/s_server.c b/apps/s_server.c
index 5dd9e8e05..bbe2492 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -215,6 +215,9 @@
 				unsigned int *id_len);
 static void init_session_cache_ctx(SSL_CTX *sctx);
 static void free_sessions(void);
+static int ssl_load_stores(SSL_CTX *sctx,
+			const char *vfyCApath, const char *vfyCAfile,
+			const char *chCApath, const char *chCAfile);
 #ifndef OPENSSL_NO_DH
 static DH *load_dh_param(const char *dhfile);
 static DH *get_dh512(void);
@@ -952,6 +955,8 @@
 	int badarg = 0;
 	short port=PORT;
 	char *CApath=NULL,*CAfile=NULL;
+	char *chCApath=NULL,*chCAfile=NULL;
+	char *vfyCApath=NULL,*vfyCAfile=NULL;
 	unsigned char *context = NULL;
 	char *dhfile = NULL;
 #ifndef OPENSSL_NO_ECDH
@@ -961,6 +966,7 @@
 	int ret=1;
 	int off=0;
 	unsigned int cert_flags = 0;
+	int build_chain = 0;
 	int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0;
 	int state=0;
 	const SSL_METHOD *meth=NULL;
@@ -1135,6 +1141,16 @@
 			if (--argc < 1) goto bad;
 			CApath= *(++argv);
 			}
+		else if	(strcmp(*argv,"-chainCApath") == 0)
+			{
+			if (--argc < 1) goto bad;
+			chCApath= *(++argv);
+			}
+		else if	(strcmp(*argv,"-verifyCApath") == 0)
+			{
+			if (--argc < 1) goto bad;
+			vfyCApath= *(++argv);
+			}
 		else if (strcmp(*argv,"-no_cache") == 0)
 			no_cache = 1;
 		else if (strcmp(*argv,"-ext_cache") == 0)
@@ -1162,11 +1178,23 @@
 			if (--argc < 1) goto bad;
 			cipher= *(++argv);
 			}
+		else if	(strcmp(*argv,"-build_chain") == 0)
+			build_chain = 1;
 		else if	(strcmp(*argv,"-CAfile") == 0)
 			{
 			if (--argc < 1) goto bad;
 			CAfile= *(++argv);
 			}
+		else if	(strcmp(*argv,"-chainCAfile") == 0)
+			{
+			if (--argc < 1) goto bad;
+			chCAfile= *(++argv);
+			}
+		else if	(strcmp(*argv,"-verifyCAfile") == 0)
+			{
+			if (--argc < 1) goto bad;
+			vfyCAfile= *(++argv);
+			}
 #ifdef FIONBIO	
 		else if	(strcmp(*argv,"-nbio") == 0)
 			{ s_nbio=1; }
@@ -1672,6 +1700,13 @@
 	if (vpm)
 		SSL_CTX_set1_param(ctx, vpm);
 
+	if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile))
+		{
+		BIO_printf(bio_err, "Error loading store locations\n");
+		ERR_print_errors(bio_err);
+		goto end;
+		}
+
 #ifndef OPENSSL_NO_TLSEXT
 	if (s_cert2)
 		{
@@ -1834,19 +1869,19 @@
 		}
 #endif
 	
-	if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain))
+	if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
 		goto end;
 #ifndef OPENSSL_NO_TLSEXT
 	if (s_authz_file != NULL && !SSL_CTX_use_authz_file(ctx, s_authz_file))
 		goto end;
 #endif
 #ifndef OPENSSL_NO_TLSEXT
-	if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2, NULL))
+	if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2, NULL, build_chain))
 		goto end; 
 #endif
 	if (s_dcert != NULL)
 		{
-		if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain))
+		if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain))
 			goto end;
 		}
 
@@ -3305,7 +3340,36 @@
 		}
 	first = NULL;
 	}
-	
+
+static int ssl_load_stores(SSL_CTX *sctx,
+			const char *vfyCApath, const char *vfyCAfile,
+			const char *chCApath, const char *chCAfile)
+	{
+	X509_STORE *vfy = NULL, *ch = NULL;
+	int rv = 0;
+	if (vfyCApath || vfyCAfile)
+		{
+		vfy = X509_STORE_new();
+		if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath))
+			goto err;
+		SSL_CTX_set1_verify_cert_store(ctx, vfy);
+		}
+	if (chCApath || chCAfile)
+		{
+		ch = X509_STORE_new();
+		if (!X509_STORE_load_locations(ch, chCAfile, chCApath))
+			goto err;
+		/*X509_STORE_set_verify_cb(ch, verify_callback);*/
+		SSL_CTX_set1_chain_cert_store(ctx, ch);
+		}
+	rv = 1;
+	err:
+	if (vfy)
+		X509_STORE_free(vfy);
+	if (ch)
+		X509_STORE_free(ch);
+	return rv;
+	}
 
 
 
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 457a5c7..3bc5ce9 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3449,6 +3449,15 @@
 			return 0;
 		return ssl3_set_req_cert_type(s->cert, parg, larg);
 
+	case SSL_CTRL_BUILD_CERT_CHAIN:
+		return ssl_build_cert_chain(s->cert, s->ctx->cert_store, larg);
+
+	case SSL_CTRL_SET_VERIFY_CERT_STORE:
+		return ssl_cert_set_cert_store(s->cert, parg, 0, larg);
+
+	case SSL_CTRL_SET_CHAIN_CERT_STORE:
+		return ssl_cert_set_cert_store(s->cert, parg, 1, larg);
+
 	default:
 		break;
 		}
@@ -3746,6 +3755,15 @@
 	case SSL_CTRL_SET_CLIENT_CERT_TYPES:
 		return ssl3_set_req_cert_type(ctx->cert, parg, larg);
 
+	case SSL_CTRL_BUILD_CERT_CHAIN:
+		return ssl_build_cert_chain(ctx->cert, ctx->cert_store, larg);
+
+	case SSL_CTRL_SET_VERIFY_CERT_STORE:
+		return ssl_cert_set_cert_store(ctx->cert, parg, 0, larg);
+
+	case SSL_CTRL_SET_CHAIN_CERT_STORE:
+		return ssl_cert_set_cert_store(ctx->cert, parg, 1, larg);
+
 	case SSL_CTRL_SET_TLSEXT_AUTHZ_SERVER_AUDIT_PROOF_CB_ARG:
 		ctx->tlsext_authz_server_audit_proof_cb_arg = parg;
 		break;
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 0e78fb7..ff6dcd7 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -656,6 +656,12 @@
  */
 #define SSL_CERT_FLAG_TLS_STRICT	0x00000001L
 
+/* Flags for building certificate chains */
+/* Treat any existing certificates as untrusted CAs */
+#define SSL_BUILD_CHAIN_FLAG_UNTRUSTED	0x1
+/* Con't include root CA in chain */
+#define SSL_BUILD_CHAIN_FLAG_NO_ROOT	0x2
+
 /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
  * they cannot be used to clear bits. */
 
@@ -1666,6 +1672,9 @@
 #define SSL_CTRL_SET_CLIENT_SIGALGS_LIST	102
 #define SSL_CTRL_GET_CLIENT_CERT_TYPES		103
 #define SSL_CTRL_SET_CLIENT_CERT_TYPES		104
+#define SSL_CTRL_BUILD_CERT_CHAIN		105
+#define SSL_CTRL_SET_VERIFY_CERT_STORE		106
+#define SSL_CTRL_SET_CHAIN_CERT_STORE		107
 
 #define DTLSv1_get_timeout(ssl, arg) \
 	SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
@@ -1716,6 +1725,17 @@
 	SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
 #define SSL_CTX_add1_chain_cert(ctx,x509) \
 	SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
+#define SSL_CTX_build_cert_chain(ctx, flags) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+
+#define SSL_CTX_set0_verify_cert_store(ctx,st) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st)
+#define SSL_CTX_set1_verify_cert_store(ctx,st) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st)
+#define SSL_CTX_set0_chain_cert_store(ctx,st) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st)
+#define SSL_CTX_set1_chain_cert_store(ctx,st) \
+	SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st)
 
 #define SSL_set0_chain(ctx,sk) \
 	SSL_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)sk)
@@ -1725,6 +1745,17 @@
 	SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
 #define SSL_add1_chain_cert(ctx,x509) \
 	SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
+#define SSL_build_cert_chain(s, flags) \
+	SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
+#define SSL_set0_verify_cert_store(s,st) \
+	SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st)
+#define SSL_set1_verify_cert_store(s,st) \
+	SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st)
+#define SSL_set0_chain_cert_store(s,st) \
+	SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st)
+#define SSL_set1_chain_cert_store(s,st) \
+	SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st)
+
 #define SSL_get1_curves(ctx, s) \
 	SSL_ctrl(ctx,SSL_CTRL_GET_CURVES,0,(char *)s)
 #define SSL_CTX_set1_curves(ctx, clist, clistlen) \
@@ -2328,6 +2359,7 @@
 #define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT		 278
 #define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT		 308
 #define SSL_F_SSL_BAD_METHOD				 160
+#define SSL_F_SSL_BUILD_CERT_CHAIN			 332
 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST			 161
 #define SSL_F_SSL_CERT_DUP				 221
 #define SSL_F_SSL_CERT_INST				 222
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 59a8544..9547814 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -403,6 +403,18 @@
 	ret->cert_cb = cert->cert_cb;
 	ret->cert_cb_arg = cert->cert_cb_arg;
 
+	if (cert->verify_store)
+		{
+		CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE);
+		ret->verify_store = cert->verify_store;
+		}
+
+	if (cert->chain_store)
+		{
+		CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE);
+		ret->chain_store = cert->chain_store;
+		}
+
 	return(ret);
 	
 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
@@ -500,6 +512,10 @@
 		OPENSSL_free(c->shared_sigalgs);
 	if (c->ctypes)
 		OPENSSL_free(c->ctypes);
+	if (c->verify_store)
+		X509_STORE_free(c->verify_store);
+	if (c->chain_store)
+		X509_STORE_free(c->chain_store);
 	OPENSSL_free(c);
 	}
 
@@ -671,13 +687,19 @@
 	{
 	X509 *x;
 	int i;
+	X509_STORE *verify_store;
 	X509_STORE_CTX ctx;
 
+	if (s->cert->verify_store)
+		verify_store = s->cert->verify_store;
+	else
+		verify_store = s->ctx->cert_store;
+
 	if ((sk == NULL) || (sk_X509_num(sk) == 0))
 		return(0);
 
 	x=sk_X509_value(sk,0);
-	if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk))
+	if(!X509_STORE_CTX_init(&ctx,verify_store,x,sk))
 		{
 		SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB);
 		return(0);
@@ -1042,12 +1064,18 @@
 
 	X509 *x;
 	STACK_OF(X509) *extra_certs;
+	X509_STORE *chain_store;
 
 	if (cpk)
 		x = cpk->x509;
 	else
 		x = NULL;
 
+	if (s->cert->chain_store)
+		chain_store = s->cert->chain_store;
+	else
+		chain_store = s->ctx->cert_store;
+
 	/* If we have a certificate specific chain use it, else use
 	 * parent ctx.
 	 */
@@ -1078,7 +1106,7 @@
 			{
 			X509_STORE_CTX xs_ctx;
 
-			if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
+			if (!X509_STORE_CTX_init(&xs_ctx,chain_store,x,NULL))
 				{
 				SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_X509_LIB);
 				return(0);
@@ -1109,3 +1137,69 @@
 	return 1;
 	}
 
+/* Build a certificate chain for current certificate */
+int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags)
+	{
+	CERT_PKEY *cpk = c->key;
+	X509_STORE_CTX xs_ctx;
+	STACK_OF(X509) *chain = NULL, *untrusted = NULL;
+	X509 *x;
+	int i;
+
+	if (!cpk->x509)
+		{
+		SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
+		return 0;
+		}
+
+	if (c->chain_store)
+		chain_store = c->chain_store;
+
+	if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
+		untrusted = cpk->chain;
+
+	if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted))
+		{
+		SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
+		return 0;
+		}
+
+	i = X509_verify_cert(&xs_ctx);
+	if (i > 0)
+		chain = X509_STORE_CTX_get1_chain(&xs_ctx);
+	X509_STORE_CTX_cleanup(&xs_ctx);
+	if (i <= 0)
+		{
+		SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
+		return 0;
+		}
+	if (cpk->chain)
+		sk_X509_pop_free(cpk->chain, X509_free);
+	/* Remove EE certificate from chain */
+	x = sk_X509_shift(chain);
+	X509_free(x);
+	if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT)
+		{
+		x = sk_X509_pop(chain);
+		X509_free(x);
+		}
+	cpk->chain = chain;
+
+	return 1;
+	}
+
+int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)
+	{
+	X509_STORE **pstore;
+	if (chain)
+		pstore = &c->chain_store;
+	else
+		pstore = &c->verify_store;
+	if (*pstore)
+		X509_STORE_free(*pstore);
+	*pstore = store;
+	if (ref && store)
+		CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
+	return 1;
+	}
+
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index a51937b..9301013 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -195,6 +195,7 @@
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),	"ssl_add_serverhello_tlsext"},
 {ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT),	"ssl_add_serverhello_use_srtp_ext"},
 {ERR_FUNC(SSL_F_SSL_BAD_METHOD),	"ssl_bad_method"},
+{ERR_FUNC(SSL_F_SSL_BUILD_CERT_CHAIN),	"ssl_build_cert_chain"},
 {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),	"ssl_bytes_to_cipher_list"},
 {ERR_FUNC(SSL_F_SSL_CERT_DUP),	"ssl_cert_dup"},
 {ERR_FUNC(SSL_F_SSL_CERT_INST),	"ssl_cert_inst"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index e64228f..7b1c12c 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -583,6 +583,12 @@
 	int (*cert_cb)(SSL *ssl, void *arg);
 	void *cert_cb_arg;
 
+	/* Optional X509_STORE for chain building or certificate validation
+	 * If NULL the parent SSL_CTX store is used instead.
+	 */
+	X509_STORE *chain_store;
+	X509_STORE *verify_store;
+
 	int references; /* >1 only if SSL_copy_session_id is used */
 	} CERT;
 
@@ -925,6 +931,8 @@
 
 int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
 int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l);
+int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags);
+int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref);
 int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
 int ssl_undefined_const_function(const SSL *s);