if (cpk->chain)
{
- int j;
- rpk->chain = sk_X509_dup(cpk->chain);
+ rpk->chain = X509_chain_up_ref(cpk->chain);
if (!rpk->chain)
{
SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
goto err;
}
- for (j = 0; j < sk_X509_num(rpk->chain); j++)
- {
- X509 *x = sk_X509_value(rpk->chain, j);
- CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
- }
}
- if (cert->pkeys[i].authz != NULL)
+ rpk->valid_flags = 0;
+#ifndef OPENSSL_NO_TLSEXT
+ if (cert->pkeys[i].serverinfo != NULL)
{
/* Just copy everything. */
- ret->pkeys[i].authz_length =
- cert->pkeys[i].authz_length;
- ret->pkeys[i].authz =
- OPENSSL_malloc(ret->pkeys[i].authz_length);
- if (ret->pkeys[i].authz == NULL)
+ ret->pkeys[i].serverinfo =
+ OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
+ if (ret->pkeys[i].serverinfo == NULL)
{
SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
- return(NULL);
+ return NULL;
}
- memcpy(ret->pkeys[i].authz,
- cert->pkeys[i].authz,
- cert->pkeys[i].authz_length);
+ ret->pkeys[i].serverinfo_length =
+ cert->pkeys[i].serverinfo_length;
+ memcpy(ret->pkeys[i].serverinfo,
+ cert->pkeys[i].serverinfo,
+ cert->pkeys[i].serverinfo_length);
}
+#endif
}
ret->references=1;
/* Peer sigalgs set to NULL as we get these from handshake too */
ret->peer_sigalgs = NULL;
ret->peer_sigalgslen = 0;
- /* Configure sigalgs however we copy across */
+ /* Configured sigalgs however we copy across */
+
if (cert->conf_sigalgs)
{
- ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen
- * sizeof(TLS_SIGALGS));
+ ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
if (!ret->conf_sigalgs)
goto err;
memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
- cert->conf_sigalgslen * sizeof(TLS_SIGALGS));
+ cert->conf_sigalgslen);
ret->conf_sigalgslen = cert->conf_sigalgslen;
}
else
ret->conf_sigalgs = NULL;
+
+ if (cert->client_sigalgs)
+ {
+ ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
+ if (!ret->client_sigalgs)
+ goto err;
+ memcpy(ret->client_sigalgs, cert->client_sigalgs,
+ cert->client_sigalgslen);
+ ret->client_sigalgslen = cert->client_sigalgslen;
+ }
+ else
+ ret->client_sigalgs = NULL;
/* Shared sigalgs also NULL */
ret->shared_sigalgs = NULL;
+ /* Copy any custom client certificate types */
+ if (cert->ctypes)
+ {
+ ret->ctypes = OPENSSL_malloc(cert->ctype_num);
+ if (!ret->ctypes)
+ goto err;
+ memcpy(ret->ctypes, cert->ctypes, cert->ctype_num);
+ ret->ctype_num = cert->ctype_num;
+ }
+
+ ret->cert_flags = cert->cert_flags;
+
+ 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;
+ }
+
+ ret->ciphers_raw = NULL;
return(ret);
cpk->chain = NULL;
}
#ifndef OPENSSL_NO_TLSEXT
- if (cpk->authz != NULL)
- OPENSSL_free(cpk->authz);
+ if (cpk->serverinfo)
+ {
+ OPENSSL_free(cpk->serverinfo);
+ cpk->serverinfo = NULL;
+ cpk->serverinfo_length = 0;
+ }
#endif
+ /* Clear all flags apart from explicit sign */
+ cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN;
}
}
OPENSSL_free(c->peer_sigalgs);
if (c->conf_sigalgs)
OPENSSL_free(c->conf_sigalgs);
+ if (c->client_sigalgs)
+ OPENSSL_free(c->client_sigalgs);
if (c->shared_sigalgs)
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);
+ if (c->ciphers_raw)
+ OPENSSL_free(c->ciphers_raw);
OPENSSL_free(c);
}
int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain)
{
STACK_OF(X509) *dchain;
- X509 *x;
- int i;
if (!chain)
return ssl_cert_set0_chain(c, NULL);
- dchain = sk_X509_dup(chain);
+ dchain = X509_chain_up_ref(chain);
if (!dchain)
return 0;
- for (i = 0; i < sk_X509_num(dchain); i++)
- {
- x = sk_X509_value(dchain, i);
- CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
- }
if (!ssl_cert_set0_chain(c, dchain))
{
sk_X509_pop_free(dchain, X509_free);
return 1;
}
+int ssl_cert_select_current(CERT *c, X509 *x)
+ {
+ int i;
+ if (x == NULL)
+ return 0;
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ {
+ CERT_PKEY *cpk = c->pkeys + i;
+ if (cpk->x509 == x && cpk->privatekey)
+ {
+ c->key = cpk;
+ return 1;
+ }
+ }
+
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ {
+ CERT_PKEY *cpk = c->pkeys + i;
+ if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x))
+ {
+ c->key = cpk;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+int ssl_cert_set_current(CERT *c, long op)
+ {
+ int i, idx;
+ if (!c)
+ return 0;
+ if (op == SSL_CERT_SET_FIRST)
+ idx = 0;
+ else if (op == SSL_CERT_SET_NEXT)
+ {
+ idx = (int)(c->key - c->pkeys + 1);
+ if (idx >= SSL_PKEY_NUM)
+ return 0;
+ }
+ else
+ return 0;
+ for (i = idx; i < SSL_PKEY_NUM; i++)
+ {
+ CERT_PKEY *cpk = c->key + i;
+ if (cpk->x509 && cpk->privatekey)
+ {
+ c->key = cpk;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg)
+ {
+ c->cert_cb = cb;
+ c->cert_cb_arg = arg;
+ }
+
SESS_CERT *ssl_sess_cert_new(void)
{
SESS_CERT *ret;
{
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);
}
+ /* Set suite B flags if needed */
+ X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s));
#if 0
if (SSL_get_verify_depth(s) >= 0)
X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
{
BUF_MEM *buf = s->init_buf;
- int no_chain;
int i;
X509 *x;
STACK_OF(X509) *extra_certs;
+ X509_STORE *chain_store;
- if (cpk)
- x = cpk->x509;
- else
- x = NULL;
+ /* TLSv1 sends a chain with nothing in it, instead of an alert */
+ if (!BUF_MEM_grow_clean(buf,10))
+ {
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_BUF_LIB);
+ return 0;
+ }
+
+ if (!cpk || !cpk->x509)
+ return 1;
+
+ x = cpk->x509;
/* If we have a certificate specific chain use it, else use
* parent ctx.
*/
- if (cpk && cpk->chain)
+ if (cpk->chain)
extra_certs = cpk->chain;
else
extra_certs = s->ctx->extra_certs;
if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
- no_chain = 1;
+ chain_store = NULL;
+ else if (s->cert->chain_store)
+ chain_store = s->cert->chain_store;
else
- no_chain = 0;
+ chain_store = s->ctx->cert_store;
- /* TLSv1 sends a chain with nothing in it, instead of an alert */
- if (!BUF_MEM_grow_clean(buf,10))
+ if (chain_store)
{
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_BUF_LIB);
- return 0;
- }
- if (x != NULL)
- {
- if (no_chain)
+ X509_STORE_CTX xs_ctx;
+
+ if (!X509_STORE_CTX_init(&xs_ctx,chain_store,x,NULL))
{
- if (!ssl_add_cert_to_buf(buf, l, x))
- return 0;
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_X509_LIB);
+ return(0);
}
- else
+ X509_verify_cert(&xs_ctx);
+ /* Don't leave errors in the queue */
+ ERR_clear_error();
+ for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
{
- X509_STORE_CTX xs_ctx;
+ x = sk_X509_value(xs_ctx.chain, i);
- if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL))
- {
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN,ERR_R_X509_LIB);
- return(0);
- }
- X509_verify_cert(&xs_ctx);
- /* Don't leave errors in the queue */
- ERR_clear_error();
- for (i=0; i < sk_X509_num(xs_ctx.chain); i++)
+ if (!ssl_add_cert_to_buf(buf, l, x))
{
- x = sk_X509_value(xs_ctx.chain, i);
-
- if (!ssl_add_cert_to_buf(buf, l, x))
- {
- X509_STORE_CTX_cleanup(&xs_ctx);
- return 0;
- }
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ return 0;
}
- X509_STORE_CTX_cleanup(&xs_ctx);
}
+ X509_STORE_CTX_cleanup(&xs_ctx);
}
- for (i=0; i<sk_X509_num(extra_certs); i++)
+ else
{
- x=sk_X509_value(extra_certs,i);
if (!ssl_add_cert_to_buf(buf, l, x))
return 0;
+ for (i=0; i<sk_X509_num(extra_certs); i++)
+ {
+ x=sk_X509_value(extra_certs,i);
+ if (!ssl_add_cert_to_buf(buf, l, x))
+ return 0;
+ }
}
+ 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, rv = 0;
+ if (!cpk->x509)
+ {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
+ goto err;
+ }
+ /* Rearranging and check the chain: add everything to a store */
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
+ {
+ chain_store = X509_STORE_new();
+ if (!chain_store)
+ goto err;
+ for (i = 0; i < sk_X509_num(cpk->chain); i++)
+ {
+ x = sk_X509_value(cpk->chain, i);
+ if (!X509_STORE_add_cert(chain_store, x))
+ goto err;
+ }
+ /* Add EE cert too: it might be self signed */
+ if (!X509_STORE_add_cert(chain_store, cpk->x509))
+ goto err;
+ }
+ else
+ {
+ 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);
+ goto err;
+ }
+ /* Set suite B flags if needed */
+ X509_STORE_CTX_set_flags(&xs_ctx, c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
+
+ i = X509_verify_cert(&xs_ctx);
+ if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR)
+ {
+ ERR_clear_error();
+ i = 1;
+ }
+ if (i > 0)
+ chain = X509_STORE_CTX_get1_chain(&xs_ctx);
+ if (i <= 0)
+ {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ i = X509_STORE_CTX_get_error(&xs_ctx);
+ ERR_add_error_data(2, "Verify error:",
+ X509_verify_cert_error_string(i));
+
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ goto err;
+ }
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ 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)
+ {
+ if (sk_X509_num(chain) > 0)
+ {
+ /* See if last cert is self signed */
+ x = sk_X509_value(chain, sk_X509_num(chain) - 1);
+ X509_check_purpose(x, -1, 0);
+ if (x->ex_flags & EXFLAG_SS)
+ {
+ x = sk_X509_pop(chain);
+ X509_free(x);
+ }
+ }
+ }
+ cpk->chain = chain;
+ rv = 1;
+ err:
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
+ X509_STORE_free(chain_store);
+
+ return rv;
+ }
+
+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;
}