summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES18
-rw-r--r--ssl/s3_lib.c83
-rw-r--r--ssl/ssl.err2
-rw-r--r--ssl/ssl.h18
-rw-r--r--ssl/ssl_cert.c21
-rw-r--r--ssl/ssl_err.c2
-rw-r--r--ssl/ssl_lib.c8
-rw-r--r--ssl/ssl_locl.h2
-rw-r--r--ssl/ssl_rsa.c109
9 files changed, 180 insertions, 83 deletions
diff --git a/CHANGES b/CHANGES
index 7bca0f5474..6b4b174435 100644
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,24 @@
Changes between 0.9.1c and 0.9.2
+ *) Add a bunch of SSL_xxx() functions for configuring the temporary RSA and
+ DH private keys and/or callback functions which directly correspond to
+ their SSL_CTX_xxx() counterparts but work on a per-connection basis. This
+ is needed for applications which have to configure certificates on a
+ per-connection basis (e.g. Apache+mod_ssl) instead of a per-context basis
+ (e.g. s_server).
+ For the RSA certificate situation is makes no difference, but
+ for the DSA certificate situation this fixes the "no shared cipher"
+ problem where the OpenSSL cipher selection procedure failed because the
+ temporary keys were not overtaken from the context and the API provided
+ no way to reconfigure them.
+ The new functions now let applications reconfigure the stuff and they
+ are in detail: SSL_need_tmp_RSA, SSL_set_tmp_rsa, SSL_set_tmp_dh,
+ SSL_set_tmp_rsa_callback and SSL_set_tmp_dh_callback. Additionally a new
+ non-public-API function ssl_cert_instantiate() is used as a helper
+ function and also to reduce code redundancy inside ssl_rsa.c.
+ [Ralf S. Engelschall]
+
*) Move s_server -dcert and -dkey options out of the undocumented feature
area because they are useful for the DSA situation and should be
recognized by the users.
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 1dd03b1265..3687862b70 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -546,6 +546,26 @@ char *parg;
{
int ret=0;
+#if !defined(NO_DSA) || !defined(NO_RSA)
+ if (
+#ifndef NO_RSA
+ cmd == SSL_CTRL_SET_TMP_RSA ||
+ cmd == SSL_CTRL_SET_TMP_RSA_CB ||
+#endif
+#ifndef NO_DSA
+ cmd == SSL_CTRL_SET_TMP_DH ||
+ cmd == SSL_CTRL_SET_TMP_DH_CB ||
+#endif
+ 0)
+ {
+ if (!ssl_cert_instantiate(&s->cert, s->ctx->default_cert))
+ {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ }
+#endif
+
switch (cmd)
{
case SSL_CTRL_GET_SESSION_REUSED:
@@ -566,6 +586,69 @@ char *parg;
case SSL_CTRL_GET_FLAGS:
ret=(int)(s->s3->flags);
break;
+#ifndef NO_RSA
+ case SSL_CTRL_NEED_TMP_RSA:
+ if ((s->cert != NULL) && (s->cert->rsa_tmp == NULL) &&
+ ((s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL) ||
+ (EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey) > (512/8))))
+ ret = 1;
+ break;
+ case SSL_CTRL_SET_TMP_RSA:
+ {
+ RSA *rsa = (RSA *)parg;
+ if (rsa == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ return(ret);
+ }
+ if ((rsa = RSAPrivateKey_dup(rsa)) == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_RSA_LIB);
+ return(ret);
+ }
+ if (s->cert->rsa_tmp != NULL)
+ RSA_free(s->cert->rsa_tmp);
+ s->cert->rsa_tmp = rsa;
+ ret = 1;
+ }
+ break;
+ case SSL_CTRL_SET_TMP_RSA_CB:
+#ifndef NOPROTO
+ s->cert->rsa_tmp_cb = (RSA *(*)(SSL *, int, int))parg;
+#else
+ s->cert->rsa_tmp_cb = (RSA *(*)())parg;
+#endif
+ break;
+#endif
+#ifndef NO_DH
+ case SSL_CTRL_SET_TMP_DH:
+ {
+ DH *dh = (DH *)parg;
+ if (dh == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ return(ret);
+ }
+ if ((dh = DHparams_dup(dh)) == NULL) {
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
+ return(ret);
+ }
+ if (!DH_generate_key(dh)) {
+ DH_free(dh);
+ SSLerr(SSL_F_SSL3_CTRL, ERR_R_DH_LIB);
+ return(ret);
+ }
+ if (s->cert->dh_tmp != NULL)
+ DH_free(s->cert->dh_tmp);
+ s->cert->dh_tmp = dh;
+ ret = 1;
+ }
+ break;
+ case SSL_CTRL_SET_TMP_DH_CB:
+#ifndef NOPROTO
+ s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))parg;
+#else
+ s->cert->dh_tmp_cb = (DH *(*)())parg;
+#endif
+ break;
+#endif
default:
break;
}
diff --git a/ssl/ssl.err b/ssl/ssl.err
index 9c8ce62712..ad86fbca50 100644
--- a/ssl/ssl.err
+++ b/ssl/ssl.err
@@ -113,6 +113,8 @@
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL3_CTRL 213
+#define SSL_F_SSL_CERT_INSTANTIATE 214
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 2a9cd7f5ab..56f08c0ea0 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -784,6 +784,13 @@ struct ssl_st
#define SSL_CTX_set_tmp_dh(ctx,dh) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+#define SSL_need_tmp_RSA(ssl) \
+ SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
+#define SSL_set_tmp_rsa(ssl,rsa) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa)
+#define SSL_set_tmp_dh(ssl,dh) \
+ SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
+
#define SSL_CTX_add_extra_chain_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
@@ -1029,6 +1036,12 @@ void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
DH *(*dh)(SSL *ssl,int export,int keylength));
+void SSL_set_tmp_rsa_callback(SSL *ssl,
+ RSA *(*cb)(SSL *ssl,int export,
+ int keylength));
+void SSL_set_tmp_dh_callback(SSL *ssl,
+ DH *(*dh)(SSL *ssl,int export,int keylength));
+
#ifdef HEADER_COMP_H
int SSL_COMP_add_compression_method(int id,COMP_METHOD *cm);
#else
@@ -1258,6 +1271,9 @@ int SSL_COMP_add_compression_method();
void SSL_CTX_set_tmp_rsa_callback();
void SSL_CTX_set_tmp_dh_callback();
+void SSL_set_tmp_rsa_callback();
+void SSL_set_tmp_dh_callback();
+
/* #endif */
#endif
@@ -1378,6 +1394,8 @@ void SSL_CTX_set_tmp_dh_callback();
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_SETUP_KEY_BLOCK 211
#define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL3_CTRL 213
+#define SSL_F_SSL_CERT_INSTANTIATE 214
/* Reason codes. */
#define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 7d4531d808..e5e1b9998e 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -144,6 +144,27 @@ CERT *c;
Free(c);
}
+int ssl_cert_instantiate(CERT **o, CERT *d)
+ {
+ CERT *n;
+ if (o == NULL)
+ {
+ SSLerr(SSL_F_SSL_CERT_INSTANTIATE, ERR_R_PASSED_NULL_PARAMETER);
+ return(0);
+ }
+ if (*o != NULL && d != NULL && *o != d)
+ return(1);
+ if ((n = ssl_cert_new()) == NULL)
+ {
+ SSLerr(SSL_F_SSL_CERT_INSTANTIATE, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ if (*o != NULL)
+ ssl_cert_free(*o);
+ *o = n;
+ return(1);
+ }
+
int ssl_set_cert_type(c, type)
CERT *c;
int type;
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index cca0763011..c850335ca1 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -175,6 +175,8 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_PACK(0,SSL_F_TLS1_ENC,0), "TLS1_ENC"},
{ERR_PACK(0,SSL_F_TLS1_SETUP_KEY_BLOCK,0), "TLS1_SETUP_KEY_BLOCK"},
{ERR_PACK(0,SSL_F_WRITE_PENDING,0), "WRITE_PENDING"},
+{ERR_PACK(0,SSL_F_SSL3_CTRL,0), "SSL3_CTRL"},
+{ERR_PACK(0,SSL_F_SSL_CERT_INSTANTIATE,0), "SSL_CERT_INSTANTIATE"},
{0,NULL},
};
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index c4be734af4..55f862fbe0 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1899,6 +1899,14 @@ void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int export,
int keylength))
{ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,0,(char *)dh); }
+void SSL_set_tmp_rsa_callback(SSL *ssl,RSA *(*cb)(SSL *ssl,int export,
+ int keylength))
+ { SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb); }
+
+void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int export,
+ int keylength))
+ { SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,0,(char *)dh); }
+
#if defined(_WINDLL) && defined(WIN16)
#include "../crypto/bio/bss_file.c"
#endif
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index e4d783aa13..3317ecc6c9 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -348,6 +348,7 @@ SSL_METHOD *sslv3_base_method(void);
void ssl_clear_cipher_ctx(SSL *s);
int ssl_clear_bad_session(SSL *s);
CERT *ssl_cert_new(void);
+int ssl_cert_instantiate(CERT **o, CERT *d);
void ssl_cert_free(CERT *c);
int ssl_set_cert_type(CERT *c, int type);
int ssl_get_new_session(SSL *s, int session);
@@ -483,6 +484,7 @@ SSL_METHOD *sslv3_base_method();
void ssl_clear_cipher_ctx();
int ssl_clear_bad_session();
CERT *ssl_cert_new();
+int ssl_cert_instantiate();
void ssl_cert_free();
int ssl_set_cert_type();
int ssl_get_new_session();
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 43c51bc2b5..8579c51fc6 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -76,27 +76,17 @@ int SSL_use_certificate(ssl, x)
SSL *ssl;
X509 *x;
{
- CERT *c;
-
if (x == NULL)
{
SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
return(0);
}
- if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
+ if (!ssl_cert_instantiate(&ssl->cert, ssl->ctx->default_cert))
{
- c=ssl_cert_new();
- if (c == NULL)
- {
- SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
- return(0);
- }
- if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
- ssl->cert=c;
+ SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+ return(0);
}
- c=ssl->cert;
-
- return(ssl_set_cert(c,x));
+ return(ssl_set_cert(ssl->cert,x));
}
#ifndef NO_STDIO
@@ -177,7 +167,6 @@ int SSL_use_RSAPrivateKey(ssl, rsa)
SSL *ssl;
RSA *rsa;
{
- CERT *c;
EVP_PKEY *pkey;
int ret;
@@ -186,19 +175,11 @@ RSA *rsa;
SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
return(0);
}
-
- if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
- {
- c=ssl_cert_new();
- if (c == NULL)
- {
- SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
- return(0);
- }
- if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
- ssl->cert=c;
+ if (!ssl_cert_instantiate(&ssl->cert, ssl->ctx->default_cert))
+ {
+ SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+ return(0);
}
- c=ssl->cert;
if ((pkey=EVP_PKEY_new()) == NULL)
{
SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
@@ -208,7 +189,7 @@ RSA *rsa;
CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
EVP_PKEY_assign_RSA(pkey,rsa);
- ret=ssl_set_pkey(c,pkey);
+ ret=ssl_set_pkey(ssl->cert,pkey);
EVP_PKEY_free(pkey);
return(ret);
}
@@ -366,7 +347,6 @@ int SSL_use_PrivateKey(ssl, pkey)
SSL *ssl;
EVP_PKEY *pkey;
{
- CERT *c;
int ret;
if (pkey == NULL)
@@ -374,21 +354,12 @@ EVP_PKEY *pkey;
SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
return(0);
}
-
- if ((ssl->cert == NULL) || (ssl->cert == ssl->ctx->default_cert))
- {
- c=ssl_cert_new();
- if (c == NULL)
- {
- SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
- return(0);
- }
- if (ssl->cert != NULL) ssl_cert_free(ssl->cert);
- ssl->cert=c;
+ if (!ssl_cert_instantiate(&ssl->cert, ssl->ctx->default_cert))
+ {
+ SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+ return(0);
}
- c=ssl->cert;
-
- ret=ssl_set_pkey(c,pkey);
+ ret=ssl_set_pkey(ssl->cert,pkey);
return(ret);
}
@@ -464,27 +435,17 @@ int SSL_CTX_use_certificate(ctx, x)
SSL_CTX *ctx;
X509 *x;
{
- CERT *c;
-
if (x == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER);
return(0);
}
-
- if (ctx->default_cert == NULL)
+ if (!ssl_cert_instantiate(&ctx->default_cert, NULL))
{
- c=ssl_cert_new();
- if (c == NULL)
- {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
- return(0);
- }
- ctx->default_cert=c;
+ SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE);
+ return(0);
}
- c=ctx->default_cert;
-
- return(ssl_set_cert(c,x));
+ return(ssl_set_cert(ctx->default_cert,x));
}
static int ssl_set_cert(c,x)
@@ -648,7 +609,6 @@ SSL_CTX *ctx;
RSA *rsa;
{
int ret;
- CERT *c;
EVP_PKEY *pkey;
if (rsa == NULL)
@@ -656,18 +616,11 @@ RSA *rsa;
SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
return(0);
}
- if (ctx->default_cert == NULL)
+ if (!ssl_cert_instantiate(&ctx->default_cert, NULL))
{
- c=ssl_cert_new();
- if (c == NULL)
- {
- SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
- return(0);
- }
- ctx->default_cert=c;
+ SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE);
+ return(0);
}
- c=ctx->default_cert;
-
if ((pkey=EVP_PKEY_new()) == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB);
@@ -677,7 +630,7 @@ RSA *rsa;
CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
EVP_PKEY_assign_RSA(pkey,rsa);
- ret=ssl_set_pkey(c,pkey);
+ ret=ssl_set_pkey(ctx->default_cert,pkey);
EVP_PKEY_free(pkey);
return(ret);
}
@@ -759,27 +712,17 @@ int SSL_CTX_use_PrivateKey(ctx, pkey)
SSL_CTX *ctx;
EVP_PKEY *pkey;
{
- CERT *c;
-
if (pkey == NULL)
{
SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER);
return(0);
}
-
- if (ctx->default_cert == NULL)
+ if (!ssl_cert_instantiate(&ctx->default_cert, NULL))
{
- c=ssl_cert_new();
- if (c == NULL)
- {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
- return(0);
- }
- ctx->default_cert=c;
+ SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE);
+ return(0);
}
- c=ctx->default_cert;
-
- return(ssl_set_pkey(c,pkey));
+ return(ssl_set_pkey(ctx->default_cert,pkey));
}
#ifndef NO_STDIO