Add support for certificate stores in CERT structure. This makes it
authorDr. Stephen Henson <steve@openssl.org>
Wed, 26 Dec 2012 15:21:53 +0000 (15:21 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 26 Dec 2012 15:21:53 +0000 (15:21 +0000)
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.
(backport from HEAD)

CHANGES
apps/s_apps.h
apps/s_cb.c
apps/s_client.c
apps/s_server.c
ssl/s3_lib.c
ssl/ssl.h
ssl/ssl_cert.c
ssl/ssl_err.c
ssl/ssl_locl.h
ssl/t1_lib.c

diff --git a/CHANGES b/CHANGES
index 9137cc8263a336dfe764ff7ff7f468ce32bb51c2..7b58b296032e6a766c35cffdc2596e83251c0c5a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,19 @@
      OID NID.
      [Steve Henson]
 
+  *) 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.
index c04e2d3611f0dae4085789648d055955eb51f5c0..c7e6926a27050ff462b2fa0979da6d95d1a7d4f4 100644 (file)
@@ -155,7 +155,7 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
 #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);
index 6e26d43de43f0a99e7e1115e39eeccc949a828a6..f994fbd93b57a7a2f22e983d5caee9fc45617768 100644 (file)
@@ -251,7 +251,7 @@ 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)
        {
        if (cert == NULL)
                return 1;
@@ -282,6 +282,13 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
                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;
        }
 
@@ -1125,6 +1132,7 @@ struct  ssl_excert_st
        X509 *cert;
        EVP_PKEY *key;
        STACK_OF(X509) *chain;
+       int build_chain;
        struct ssl_excert_st *next, *prev;
        };
 
@@ -1152,7 +1160,16 @@ static int set_cert_cb(SSL *ssl, void *arg)
                        {
                        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;
@@ -1178,6 +1195,7 @@ static int ssl_excert_prepend(SSL_EXCERT **pexc)
        exc->key = NULL;
        exc->chain = NULL;
        exc->prev = NULL;
+       exc->build_chain = 0;
 
        exc->next = *pexc;
        *pexc = exc;
@@ -1262,6 +1280,7 @@ int args_excert(char ***pargs, int *pargc,
        {
        char *arg = **pargs, *argn = (*pargs)[1];
        SSL_EXCERT *exc = *pexc;
+       int narg = 2;
        if (!exc)
                {
                if (ssl_excert_prepend(&exc))
@@ -1318,6 +1337,11 @@ int args_excert(char ***pargs, int *pargc,
                        }
                exc->chainfile = argn;
                }
+       else if (strcmp(arg,"-xchain_build") == 0)
+               {
+               narg = 1;
+               exc->build_chain = 1;
+               }
        else if (strcmp(arg,"-xcertform") == 0)
                {
                if (!argn)
@@ -1339,10 +1363,10 @@ int args_excert(char ***pargs, int *pargc,
        else
                return 0;
 
-       (*pargs) += 2;
+       (*pargs) += narg;
 
        if (pargc)
-               *pargc -= 2;
+               *pargc -= narg;
 
        *pexc = exc;
 
index 999bd2043ca7eab33aa51c7eb65041255ad2c0c1..90b6af80cb5ff0ecd8dddc91317b484cf2f87051 100644 (file)
@@ -558,6 +558,7 @@ int MAIN(int argc, char **argv)
        {
        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;
@@ -867,6 +868,8 @@ int MAIN(int argc, char **argv)
                        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;
@@ -1201,8 +1204,6 @@ bad:
 #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)))
@@ -1212,6 +1213,9 @@ bad:
                /* 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)) {
index 92ca0a7f85d3741a8732f4537689c3c03542c618..cabe0980a69affcc8efc20ed2ff7835fbda6588d 100644 (file)
@@ -212,6 +212,9 @@ static int init_ssl_connection(SSL *s);
 static void print_stats(BIO *bp,SSL_CTX *ctx);
 static int generate_session_id(const SSL *ssl, unsigned char *id,
                                unsigned int *id_len);
+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);
@@ -942,6 +945,8 @@ int MAIN(int argc, char *argv[])
        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
@@ -951,6 +956,7 @@ int MAIN(int argc, char *argv[])
        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;
@@ -1125,6 +1131,16 @@ int MAIN(int argc, char *argv[])
                        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 (args_verify(&argv, &argc, &badarg, bio_err, &vpm))
@@ -1150,11 +1166,23 @@ int MAIN(int argc, char *argv[])
                        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; }
@@ -1647,6 +1675,13 @@ bad:
        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)
                {
@@ -1807,19 +1842,19 @@ bad:
                }
 #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;
                }
 
@@ -3139,3 +3174,33 @@ static int generate_session_id(const SSL *ssl, unsigned char *id,
                return 0;
        return 1;
        }
+
+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;
+       }
index 12fc9bd6bb79770c9d915b093a32c3f4d244d394..2932b9fca146e7251b26b01212c055ac0f5d2f0b 100644 (file)
@@ -3449,6 +3449,15 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
                        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;
                }
@@ -3741,6 +3750,15 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
        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;
index a327daa6e7e17a61761c8c6b22fb4bfc9d305b67..daac6965d89b8f86de0006121c5991d89abe1ac9 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -656,6 +656,12 @@ struct ssl_session_st
  */
 #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. */
 
@@ -1657,6 +1663,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 #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)
@@ -1707,6 +1716,17 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
        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)
@@ -1716,6 +1736,17 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
        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) \
@@ -2308,6 +2339,7 @@ void ERR_load_SSL_strings(void);
 #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
index 59a8544431e15ae0f809e2c100e3ad7ce4b3f118..95478141a8a8b5058ee89da43e85bde9c61d53fa 100644 (file)
@@ -403,6 +403,18 @@ CERT *ssl_cert_dup(CERT *cert)
        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 @@ void ssl_cert_free(CERT *c)
                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 @@ int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk)
        {
        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 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
 
        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 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
                        {
                        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 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
        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;
+       }
+
index f5eb6ff76fb7035390a3c53db2393509611b37cb..99192e918288a0ee063426a55a4a2eda4211af15 100644 (file)
@@ -195,6 +195,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {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"},
index d26ff9863c5dabe5044b6720f422a6b4965b271e..874d12b3b9e7b38d1d3b40c9107e86278c94ab75 100644 (file)
@@ -585,6 +585,12 @@ typedef struct cert_st
        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;
 
@@ -927,6 +933,8 @@ void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg);
 
 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);
index 25723d33a391b54452fd6d7cdf4cf975768e5b15..d84c24df8f1c70a3890698d8494e441043c7942e 100644 (file)
@@ -583,7 +583,7 @@ int tls1_check_ec_tmp_key(SSL *s)
                        return 0;
                }
        if (!tls1_set_ec_id(curve_id, NULL, ec))
-               return 1;
+               return 0;
        return tls1_check_ec_key(s, curve_id, NULL);
        }