diff --git a/CHANGES b/CHANGES index 7bca0f54740b89cf3b8f73df9e58869d31796a63..6b4b174435222c48d7ed7bf4f90f2ec215b23817 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 1dd03b1265553b70866cf698ccce6dda29b5513c..3687862b70680ff7e37b5ca41b2979a6faf30f58 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 9c8ce62712771199c4017116a2ee5d9b1dc32d8d..ad86fbca5049f1084f125e2e4e66eec0e6eea534 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 2a9cd7f5abdab2c2b4d779e2288c6e67662e28a1..56f08c0ea0887706ec28eb7f6236f652fb36faee 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 7d4531d808ec6ad7f32d38d61f58d9b9706f2326..e5e1b9998e2098be2475d29c15cabbc4119ffeeb 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 cca07630118aec6b220c1d6abc636b80c1a8b894..c850335ca180030b51814765d88f9d80a2764930 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 c4be734af4feaabf03c29be1da77b71d59f54c91..55f862fbe03a725a7969f8a21a478192b954e84a 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 e4d783aa13491e16cb9849ce21145f47d0834e25..3317ecc6c9b8a1e9e84c81f0452a55d3706f1c24 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 43c51bc2b53bd23fd6dca0f1e6762f757644cd8e..8579c51fc6234863daaa2e1a13a3c966274a4777 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