* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
#include <stdio.h>
-#include "openssl/e_os.h"
-
+#include "e_os.h"
#ifndef NO_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if !defined(WIN32) && !defined(VSM) && !defined(NeXT) && !defined(MAC_OS_pre_X)
-#include <dirent.h>
-#endif
-
-#ifdef NeXT
-#include <sys/dir.h>
-#define dirent direct
-#endif
-
+#include "o_dir.h"
#include <openssl/objects.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#include <openssl/bn.h>
#include "ssl_locl.h"
int SSL_get_ex_data_X509_STORE_CTX_idx(void)
{
- static int ssl_x509_store_ctx_idx= -1;
+ static volatile int ssl_x509_store_ctx_idx= -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);
+ /* any write lock will do; usually this branch
+ * will only be taken once anyway */
+ CRYPTO_w_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_w_unlock(CRYPTO_LOCK_SSL_CTX);
}
- return(ssl_x509_store_ctx_idx);
+ return ssl_x509_store_ctx_idx;
}
CERT *ssl_cert_new(void)
ret->mask = cert->mask;
ret->export_mask = cert->export_mask;
-#ifndef NO_RSA
+#ifndef OPENSSL_NO_RSA
if (cert->rsa_tmp != NULL)
{
+ RSA_up_ref(cert->rsa_tmp);
ret->rsa_tmp = cert->rsa_tmp;
- CRYPTO_add(&ret->rsa_tmp->references, 1, CRYPTO_LOCK_RSA);
}
ret->rsa_tmp_cb = cert->rsa_tmp_cb;
#endif
-#ifndef NO_DH
+#ifndef OPENSSL_NO_DH
if (cert->dh_tmp != NULL)
{
- /* DH parameters don't have a reference count */
ret->dh_tmp = DHparams_dup(cert->dh_tmp);
if (ret->dh_tmp == NULL)
{
ret->dh_tmp_cb = cert->dh_tmp_cb;
#endif
+#ifndef OPENSSL_NO_ECDH
+ if (cert->ecdh_tmp)
+ {
+ ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
+ if (ret->ecdh_tmp == NULL)
+ {
+ SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+ ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
+#endif
+
for (i = 0; i < SSL_PKEY_NUM; i++)
{
if (cert->pkeys[i].x509 != NULL)
case SSL_PKEY_DH_DSA:
/* We have a DH key. */
break;
-
+
+ case SSL_PKEY_ECC:
+ /* We have an ECC key */
+ break;
+
default:
/* Can't happen. */
SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG);
return(ret);
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
err:
-#ifndef NO_RSA
+#endif
+#ifndef OPENSSL_NO_RSA
if (ret->rsa_tmp != NULL)
RSA_free(ret->rsa_tmp);
#endif
-#ifndef NO_DH
+#ifndef OPENSSL_NO_DH
if (ret->dh_tmp != NULL)
DH_free(ret->dh_tmp);
#endif
+#ifndef OPENSSL_NO_ECDH
+ if (ret->ecdh_tmp != NULL)
+ EC_KEY_free(ret->ecdh_tmp);
+#endif
for (i = 0; i < SSL_PKEY_NUM; i++)
{
}
#endif
-#ifndef NO_RSA
+#ifndef OPENSSL_NO_RSA
if (c->rsa_tmp) RSA_free(c->rsa_tmp);
#endif
-#ifndef NO_DH
+#ifndef OPENSSL_NO_DH
if (c->dh_tmp) DH_free(c->dh_tmp);
#endif
+#ifndef OPENSSL_NO_ECDH
+ if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp);
+#endif
for (i=0; i<SSL_PKEY_NUM; i++)
{
#endif
}
-#ifndef NO_RSA
+#ifndef OPENSSL_NO_RSA
if (sc->peer_rsa_tmp != NULL)
RSA_free(sc->peer_rsa_tmp);
#endif
-#ifndef NO_DH
+#ifndef OPENSSL_NO_DH
if (sc->peer_dh_tmp != NULL)
DH_free(sc->peer_dh_tmp);
#endif
+#ifndef OPENSSL_NO_ECDH
+ if (sc->peer_ecdh_tmp != NULL)
+ EC_KEY_free(sc->peer_ecdh_tmp);
+#endif
OPENSSL_free(sc);
}
return(0);
x=sk_X509_value(sk,0);
- X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk);
+ if(!X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk))
+ {
+ 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));
+#endif
X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s);
- /* We need to set the verify purpose. The purpose can be determined by
+
+ /* We need to inherit the verify parameters. These can be determined by
* the context: if its a server it will verify SSL client certificates
* or vice versa.
- */
+ */
- if(s->server) i = X509_PURPOSE_SSL_CLIENT;
- else i = X509_PURPOSE_SSL_SERVER;
+ X509_STORE_CTX_set_default(&ctx,
+ s->server ? "ssl_client" : "ssl_server");
- X509_STORE_CTX_purpose_inherit(&ctx, i, s->purpose, s->trust);
+ if (s->verify_callback)
+ X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
if (s->ctx->app_verify_callback != NULL)
+#if 1 /* new with OpenSSL 0.9.7 */
+ i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
+#else
i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */
+#endif
else
{
-#ifndef NO_X509_VERIFY
+#ifndef OPENSSL_NO_X509_VERIFY
i=X509_verify_cert(&ctx);
#else
i=0;
return(i);
}
-static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *list)
+static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *name_list)
{
if (*ca_list != NULL)
sk_X509_NAME_pop_free(*ca_list,X509_NAME_free);
- *ca_list=list;
+ *ca_list=name_list;
}
STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk)
return(ret);
}
-void SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *list)
+void SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *name_list)
{
- set_client_CA_list(&(s->client_CA),list);
+ set_client_CA_list(&(s->client_CA),name_list);
}
-void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *list)
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *name_list)
{
- set_client_CA_list(&(ctx->client_CA),list);
+ set_client_CA_list(&(ctx->client_CA),name_list);
}
-STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(SSL_CTX *ctx)
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
{
return(ctx->client_CA);
}
-STACK_OF(X509_NAME) *SSL_get_client_CA_list(SSL *s)
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
{
if (s->type == SSL_ST_CONNECT)
{ /* we are in the client */
return(X509_NAME_cmp(*a,*b));
}
-#ifndef NO_STDIO
+#ifndef OPENSSL_NO_STDIO
/*!
* Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
* it doesn't really have anything to do with clients (except that a common use
BIO *in;
X509 *x=NULL;
X509_NAME *xn=NULL;
- STACK_OF(X509_NAME) *ret,*sk;
+ STACK_OF(X509_NAME) *ret = NULL,*sk;
- ret=sk_X509_NAME_new(NULL);
sk=sk_X509_NAME_new(xname_cmp);
in=BIO_new(BIO_s_file_internal());
- if ((ret == NULL) || (sk == NULL) || (in == NULL))
+ if ((sk == NULL) || (in == NULL))
{
SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
goto err;
{
if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
break;
+ if (ret == NULL)
+ {
+ ret = sk_X509_NAME_new_null();
+ if (ret == NULL)
+ {
+ SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
if ((xn=X509_get_subject_name(x)) == NULL) goto err;
/* check for duplicates */
xn=X509_NAME_dup(xn);
if (sk != NULL) sk_X509_NAME_free(sk);
if (in != NULL) BIO_free(in);
if (x != NULL) X509_free(x);
+ if (ret != NULL)
+ ERR_clear_error();
return(ret);
}
#endif
* certs may have been added to \c stack.
*/
-#ifndef WIN32
-#ifndef VMS /* XXXX This may be fixed in the future */
-#ifndef MAC_OS_pre_X
-
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
const char *dir)
{
- DIR *d;
- struct dirent *dstruct;
+ OPENSSL_DIR_CTX *d = NULL;
+ const char *filename;
int ret = 0;
CRYPTO_w_lock(CRYPTO_LOCK_READDIR);
- d = opendir(dir);
/* Note that a side effect is that the CAs will be sorted by name */
- if(!d)
- {
- SYSerr(SYS_F_OPENDIR, get_last_sys_error());
- ERR_add_error_data(3, "opendir('", dir, "')");
- SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
- goto err;
- }
-
- while((dstruct=readdir(d)))
+
+ while((filename = OPENSSL_DIR_read(&d, dir)))
{
char buf[1024];
int r;
-
- if(strlen(dir)+strlen(dstruct->d_name)+2 > sizeof buf)
+
+ if(strlen(dir)+strlen(filename)+2 > sizeof buf)
{
SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,SSL_R_PATH_TOO_LONG);
goto err;
}
-
- r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,dstruct->d_name);
- if (r <= 0 || r >= sizeof buf)
+
+#ifdef OPENSSL_SYS_VMS
+ r = BIO_snprintf(buf,sizeof buf,"%s%s",dir,filename);
+#else
+ r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,filename);
+#endif
+ if (r <= 0 || r >= (int)sizeof(buf))
goto err;
if(!SSL_add_file_cert_subjects_to_stack(stack,buf))
goto err;
}
+
+ if (errno)
+ {
+ SYSerr(SYS_F_OPENDIR, get_last_sys_error());
+ ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
+ SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
+ goto err;
+ }
+
ret = 1;
-err:
+err:
+ if (d) OPENSSL_DIR_end(&d);
CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
return ret;
}
-#endif
-#endif
-#endif