Update OpenSSL to version 1.0.2g
This commit is contained in:
@@ -139,29 +139,50 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
|
||||
static volatile int ssl_x509_store_ctx_idx = -1;
|
||||
int got_write_lock = 0;
|
||||
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
|
||||
if (((size_t)&ssl_x509_store_ctx_idx &
|
||||
(sizeof(ssl_x509_store_ctx_idx) - 1))
|
||||
== 0) { /* check alignment, practically always true */
|
||||
int ret;
|
||||
|
||||
if (ssl_x509_store_ctx_idx < 0) {
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
|
||||
got_write_lock = 1;
|
||||
if ((ret = ssl_x509_store_ctx_idx) < 0) {
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
|
||||
if ((ret = ssl_x509_store_ctx_idx) < 0) {
|
||||
ret = ssl_x509_store_ctx_idx =
|
||||
X509_STORE_CTX_get_ex_new_index(0,
|
||||
"SSL for verify callback",
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else { /* commonly eliminated */
|
||||
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
|
||||
|
||||
if (ssl_x509_store_ctx_idx < 0) {
|
||||
ssl_x509_store_ctx_idx =
|
||||
X509_STORE_CTX_get_ex_new_index(0, "SSL for verify callback",
|
||||
NULL, NULL, NULL);
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
|
||||
got_write_lock = 1;
|
||||
|
||||
if (ssl_x509_store_ctx_idx < 0) {
|
||||
ssl_x509_store_ctx_idx =
|
||||
X509_STORE_CTX_get_ex_new_index(0,
|
||||
"SSL for verify callback",
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (got_write_lock)
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
|
||||
else
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
|
||||
|
||||
return ssl_x509_store_ctx_idx;
|
||||
}
|
||||
|
||||
if (got_write_lock)
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
|
||||
else
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
|
||||
|
||||
return ssl_x509_store_ctx_idx;
|
||||
}
|
||||
|
||||
static void ssl_cert_set_default_md(CERT *cert)
|
||||
void ssl_cert_set_default_md(CERT *cert)
|
||||
{
|
||||
/* Set digest values to defaults */
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
@@ -263,31 +284,111 @@ CERT *ssl_cert_dup(CERT *cert)
|
||||
}
|
||||
}
|
||||
ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
|
||||
ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
if (cert->pkeys[i].x509 != NULL) {
|
||||
ret->pkeys[i].x509 = cert->pkeys[i].x509;
|
||||
CRYPTO_add(&ret->pkeys[i].x509->references, 1, CRYPTO_LOCK_X509);
|
||||
CERT_PKEY *cpk = cert->pkeys + i;
|
||||
CERT_PKEY *rpk = ret->pkeys + i;
|
||||
if (cpk->x509 != NULL) {
|
||||
rpk->x509 = cpk->x509;
|
||||
CRYPTO_add(&rpk->x509->references, 1, CRYPTO_LOCK_X509);
|
||||
}
|
||||
|
||||
if (cert->pkeys[i].privatekey != NULL) {
|
||||
ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
|
||||
CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
|
||||
CRYPTO_LOCK_EVP_PKEY);
|
||||
if (cpk->privatekey != NULL) {
|
||||
rpk->privatekey = cpk->privatekey;
|
||||
CRYPTO_add(&cpk->privatekey->references, 1, CRYPTO_LOCK_EVP_PKEY);
|
||||
}
|
||||
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
rpk->valid_flags = 0;
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if (cert->pkeys[i].serverinfo != NULL) {
|
||||
/* Just copy everything. */
|
||||
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;
|
||||
}
|
||||
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->extra_certs *should* exist, but currently the own certificate
|
||||
* chain is held inside SSL_CTX
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set digests to defaults. NB: we don't copy existing values as they
|
||||
* will be set during handshake.
|
||||
*/
|
||||
ssl_cert_set_default_md(ret);
|
||||
/* Peer sigalgs set to NULL as we get these from handshake too */
|
||||
ret->peer_sigalgs = NULL;
|
||||
ret->peer_sigalgslen = 0;
|
||||
/* Configured sigalgs however we copy across */
|
||||
|
||||
if (cert->conf_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);
|
||||
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;
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if (!custom_exts_copy(&ret->cli_ext, &cert->cli_ext))
|
||||
goto err;
|
||||
if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext))
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
|
||||
@@ -307,16 +408,49 @@ CERT *ssl_cert_dup(CERT *cert)
|
||||
EC_KEY_free(ret->ecdh_tmp);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
if (ret->pkeys[i].x509 != NULL)
|
||||
X509_free(ret->pkeys[i].x509);
|
||||
if (ret->pkeys[i].privatekey != NULL)
|
||||
EVP_PKEY_free(ret->pkeys[i].privatekey);
|
||||
}
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
custom_exts_free(&ret->cli_ext);
|
||||
custom_exts_free(&ret->srv_ext);
|
||||
#endif
|
||||
|
||||
ssl_cert_clear_certs(ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free up and clear all certificates and chains */
|
||||
|
||||
void ssl_cert_clear_certs(CERT *c)
|
||||
{
|
||||
int i;
|
||||
if (c == NULL)
|
||||
return;
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
CERT_PKEY *cpk = c->pkeys + i;
|
||||
if (cpk->x509) {
|
||||
X509_free(cpk->x509);
|
||||
cpk->x509 = NULL;
|
||||
}
|
||||
if (cpk->privatekey) {
|
||||
EVP_PKEY_free(cpk->privatekey);
|
||||
cpk->privatekey = NULL;
|
||||
}
|
||||
if (cpk->chain) {
|
||||
sk_X509_pop_free(cpk->chain, X509_free);
|
||||
cpk->chain = NULL;
|
||||
}
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void ssl_cert_free(CERT *c)
|
||||
{
|
||||
int i;
|
||||
@@ -350,16 +484,27 @@ void ssl_cert_free(CERT *c)
|
||||
EC_KEY_free(c->ecdh_tmp);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
if (c->pkeys[i].x509 != NULL)
|
||||
X509_free(c->pkeys[i].x509);
|
||||
if (c->pkeys[i].privatekey != NULL)
|
||||
EVP_PKEY_free(c->pkeys[i].privatekey);
|
||||
#if 0
|
||||
if (c->pkeys[i].publickey != NULL)
|
||||
EVP_PKEY_free(c->pkeys[i].publickey);
|
||||
ssl_cert_clear_certs(c);
|
||||
if (c->peer_sigalgs)
|
||||
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);
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
custom_exts_free(&c->cli_ext);
|
||||
custom_exts_free(&c->srv_ext);
|
||||
#endif
|
||||
}
|
||||
OPENSSL_free(c);
|
||||
}
|
||||
|
||||
@@ -388,6 +533,104 @@ int ssl_cert_inst(CERT **o)
|
||||
return (1);
|
||||
}
|
||||
|
||||
int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain)
|
||||
{
|
||||
CERT_PKEY *cpk = c->key;
|
||||
if (!cpk)
|
||||
return 0;
|
||||
if (cpk->chain)
|
||||
sk_X509_pop_free(cpk->chain, X509_free);
|
||||
cpk->chain = chain;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain)
|
||||
{
|
||||
STACK_OF(X509) *dchain;
|
||||
if (!chain)
|
||||
return ssl_cert_set0_chain(c, NULL);
|
||||
dchain = X509_chain_up_ref(chain);
|
||||
if (!dchain)
|
||||
return 0;
|
||||
if (!ssl_cert_set0_chain(c, dchain)) {
|
||||
sk_X509_pop_free(dchain, X509_free);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl_cert_add0_chain_cert(CERT *c, X509 *x)
|
||||
{
|
||||
CERT_PKEY *cpk = c->key;
|
||||
if (!cpk)
|
||||
return 0;
|
||||
if (!cpk->chain)
|
||||
cpk->chain = sk_X509_new_null();
|
||||
if (!cpk->chain || !sk_X509_push(cpk->chain, x))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl_cert_add1_chain_cert(CERT *c, X509 *x)
|
||||
{
|
||||
if (!ssl_cert_add0_chain_cert(c, x))
|
||||
return 0;
|
||||
CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
|
||||
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->pkeys + 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;
|
||||
@@ -466,16 +709,24 @@ 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);
|
||||
}
|
||||
/* 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));
|
||||
@@ -797,3 +1048,210 @@ int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add a certificate to a BUF_MEM structure */
|
||||
|
||||
static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
|
||||
{
|
||||
int n;
|
||||
unsigned char *p;
|
||||
|
||||
n = i2d_X509(x, NULL);
|
||||
if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
|
||||
SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF, ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
p = (unsigned char *)&(buf->data[*l]);
|
||||
l2n3(n, p);
|
||||
i2d_X509(x, &p);
|
||||
*l += n + 3;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add certificate chain to internal SSL BUF_MEM strcuture */
|
||||
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;
|
||||
|
||||
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.
|
||||
*/
|
||||
if (cpk && 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;
|
||||
else
|
||||
no_chain = 0;
|
||||
|
||||
/* 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 (x != NULL) {
|
||||
if (no_chain) {
|
||||
if (!ssl_add_cert_to_buf(buf, l, x))
|
||||
return 0;
|
||||
} else {
|
||||
X509_STORE_CTX xs_ctx;
|
||||
|
||||
if (!X509_STORE_CTX_init(&xs_ctx, chain_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++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
unsigned long error;
|
||||
|
||||
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)) {
|
||||
error = ERR_peek_last_error();
|
||||
if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
|
||||
ERR_GET_REASON(error) !=
|
||||
X509_R_CERT_ALREADY_IN_HASH_TABLE)
|
||||
goto err;
|
||||
ERR_clear_error();
|
||||
}
|
||||
}
|
||||
/* Add EE cert too: it might be self signed */
|
||||
if (!X509_STORE_add_cert(chain_store, cpk->x509)) {
|
||||
error = ERR_peek_last_error();
|
||||
if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
|
||||
ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
|
||||
goto err;
|
||||
ERR_clear_error();
|
||||
}
|
||||
} 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) {
|
||||
if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
|
||||
ERR_clear_error();
|
||||
i = 1;
|
||||
rv = 2;
|
||||
}
|
||||
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;
|
||||
if (rv == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user