* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
return ssl_x509_store_ctx_idx;
}
+static void ssl_cert_set_default_md(CERT *cert)
+ {
+ /* Set digest values to defaults */
+#ifndef OPENSSL_NO_DSA
+ cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1();
+#endif
+#ifndef OPENSSL_NO_RSA
+ cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
+ cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_ECDSA
+ cert->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa();
+#endif
+ }
+
CERT *ssl_cert_new(void)
{
CERT *ret;
ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
ret->references=1;
-
+ ssl_cert_set_default_md(ret);
return(ret);
}
* if you find that more readable */
ret->valid = cert->valid;
- ret->mask = cert->mask;
- ret->export_mask = cert->export_mask;
+ ret->mask_k = cert->mask_k;
+ ret->mask_a = cert->mask_a;
+ ret->export_mask_k = cert->export_mask_k;
+ ret->export_mask_a = cert->export_mask_a;
#ifndef OPENSSL_NO_RSA
if (cert->rsa_tmp != NULL)
for (i = 0; i < SSL_PKEY_NUM; i++)
{
- if (cert->pkeys[i].x509 != NULL)
+ CERT_PKEY *cpk = cert->pkeys + i;
+ CERT_PKEY *rpk = ret->pkeys + i;
+ if (cpk->x509 != NULL)
{
- ret->pkeys[i].x509 = cert->pkeys[i].x509;
- CRYPTO_add(&ret->pkeys[i].x509->references, 1,
- CRYPTO_LOCK_X509);
+ rpk->x509 = cpk->x509;
+ CRYPTO_add(&rpk->x509->references, 1, CRYPTO_LOCK_X509);
}
- if (cert->pkeys[i].privatekey != NULL)
+ if (cpk->privatekey != NULL)
{
- ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
- CRYPTO_add(&ret->pkeys[i].privatekey->references, 1,
+ rpk->privatekey = cpk->privatekey;
+ CRYPTO_add(&cpk->privatekey->references, 1,
CRYPTO_LOCK_EVP_PKEY);
switch(i)
SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
}
}
+
+ if (cpk->chain)
+ {
+ rpk->chain = sk_X509_dup(cpk->chain);
+ if (!rpk->chain)
+ {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ for (i = 0; i < sk_X509_num(rpk->chain); i++)
+ {
+ X509 *x = sk_X509_value(rpk->chain, i);
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+ }
+ }
}
- /* ret->extra_certs *should* exist, but currently the own certificate
- * chain is held inside SSL_CTX */
-
ret->references=1;
+ /* Set digests to defaults. NB: we don't copy existing values as they
+ * will be set during handshake.
+ */
+ ssl_cert_set_default_md(ret);
return(ret);
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);
+ CERT_PKEY *rpk = ret->pkeys + i;
+ if (rpk->x509 != NULL)
+ X509_free(rpk->x509);
+ if (rpk->privatekey != NULL)
+ EVP_PKEY_free(rpk->privatekey);
+ if (rpk->chain)
+ sk_X509_pop_free(rpk->chain, X509_free);
}
+
return NULL;
}
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);
+ CERT_PKEY *cpk = c->pkeys + i;
+ if (cpk->x509 != NULL)
+ X509_free(cpk->x509);
+ if (cpk->privatekey != NULL)
+ EVP_PKEY_free(cpk->privatekey);
+ if (cpk->chain)
+ sk_X509_pop_free(cpk->chain, X509_free);
#if 0
if (c->pkeys[i].publickey != NULL)
EVP_PKEY_free(c->pkeys[i].publickey);
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;
+ X509 *x;
+ int i;
+ if (!chain)
+ return ssl_cert_set0_chain(c, NULL);
+ dchain = sk_X509_dup(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 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;
+ }
SESS_CERT *ssl_sess_cert_new(void)
{
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,ERR_R_X509_LIB);
return(0);
}
- if (s->param)
- X509_VERIFY_PARAM_inherit(X509_STORE_CTX_get0_param(&ctx),
- s->param);
#if 0
if (SSL_get_verify_depth(s) >= 0)
X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
X509_STORE_CTX_set_default(&ctx,
s->server ? "ssl_client" : "ssl_server");
+ /* Anything non-default in "param" should overwrite anything in the
+ * ctx.
+ */
+ X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param);
if (s->verify_callback)
X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
sk_X509_NAME_push(stack,xn);
}
+ ERR_clear_error();
+
if (0)
{
err:
if(x != NULL)
X509_free(x);
- sk_X509_NAME_set_cmp_func(stack,oldcmp);
+ (void)sk_X509_NAME_set_cmp_func(stack,oldcmp);
return ret;
}
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;
+
+ if (cpk)
+ x = cpk->x509;
+ else
+ x = NULL;
+
+ /* 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,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++)
+ {
+ 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;
+ }
+