Auto DH support.
Add auto DH parameter support. This is roughly equivalent to the ECDH auto curve selection but for DH. An application can just call SSL_CTX_set_auto_dh(ctx, 1); and appropriate DH parameters will be used based on the size of the server key. Unlike ECDH there is no way a peer can indicate the range of DH parameters it supports. Some peers cannot handle DH keys larger that 1024 bits for example. In this case if you call: SSL_CTX_set_auto_dh(ctx, 2); Only 1024 bit DH parameters will be used. If the server key is 7680 bits or more in size then 8192 bit DH parameters will be used: these will be *very* slow. The old export ciphersuites aren't supported but those are very insecure anyway.
This commit is contained in:
parent
2514fa79ac
commit
09599b52d4
8 changed files with 101 additions and 35 deletions
|
@ -218,7 +218,6 @@ static void init_session_cache_ctx(SSL_CTX *sctx);
|
||||||
static void free_sessions(void);
|
static void free_sessions(void);
|
||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
static DH *load_dh_param(const char *dhfile);
|
static DH *load_dh_param(const char *dhfile);
|
||||||
static DH *get_dh512(void);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MONOLITH
|
#ifdef MONOLITH
|
||||||
|
@ -239,33 +238,6 @@ static int client_provided_client_authz = 0;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_DH
|
|
||||||
static unsigned char dh512_p[]={
|
|
||||||
0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
|
|
||||||
0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
|
|
||||||
0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
|
|
||||||
0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
|
|
||||||
0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
|
|
||||||
0x47,0x74,0xE8,0x33,
|
|
||||||
};
|
|
||||||
static unsigned char dh512_g[]={
|
|
||||||
0x02,
|
|
||||||
};
|
|
||||||
|
|
||||||
static DH *get_dh512(void)
|
|
||||||
{
|
|
||||||
DH *dh=NULL;
|
|
||||||
|
|
||||||
if ((dh=DH_new()) == NULL) return(NULL);
|
|
||||||
dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
|
|
||||||
dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
|
|
||||||
if ((dh->p == NULL) || (dh->g == NULL))
|
|
||||||
return(NULL);
|
|
||||||
return(dh);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* static int load_CA(SSL_CTX *ctx, char *file);*/
|
/* static int load_CA(SSL_CTX *ctx, char *file);*/
|
||||||
|
|
||||||
#undef BUFSIZZ
|
#undef BUFSIZZ
|
||||||
|
@ -1931,11 +1903,18 @@ bad:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BIO_printf(bio_s_out,"Using default temp DH parameters\n");
|
BIO_printf(bio_s_out,"Using default temp DH parameters\n");
|
||||||
dh=get_dh512();
|
|
||||||
}
|
}
|
||||||
(void)BIO_flush(bio_s_out);
|
(void)BIO_flush(bio_s_out);
|
||||||
|
|
||||||
SSL_CTX_set_tmp_dh(ctx,dh);
|
if (dh == NULL)
|
||||||
|
SSL_CTX_set_dh_auto(ctx, 1);
|
||||||
|
else if (!SSL_CTX_set_tmp_dh(ctx,dh))
|
||||||
|
{
|
||||||
|
BIO_puts(bio_err, "Error setting temp DH parameters\n");
|
||||||
|
ERR_print_errors(bio_err);
|
||||||
|
DH_free(dh);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
#ifndef OPENSSL_NO_TLSEXT
|
#ifndef OPENSSL_NO_TLSEXT
|
||||||
if (ctx2)
|
if (ctx2)
|
||||||
{
|
{
|
||||||
|
@ -1951,7 +1930,15 @@ bad:
|
||||||
dh = dh2;
|
dh = dh2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SSL_CTX_set_tmp_dh(ctx2,dh);
|
if (dh == NULL)
|
||||||
|
SSL_CTX_set_dh_auto(ctx2, 1);
|
||||||
|
else if (!SSL_CTX_set_tmp_dh(ctx2,dh))
|
||||||
|
{
|
||||||
|
BIO_puts(bio_err, "Error setting temp DH parameters\n");
|
||||||
|
ERR_print_errors(bio_err);
|
||||||
|
DH_free(dh);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DH_free(dh);
|
DH_free(dh);
|
||||||
|
|
|
@ -3254,6 +3254,9 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SSL_CTRL_SET_DH_AUTO:
|
||||||
|
s->cert->dh_tmp_auto = larg;
|
||||||
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_ECDH
|
#ifndef OPENSSL_NO_ECDH
|
||||||
case SSL_CTRL_SET_TMP_ECDH:
|
case SSL_CTRL_SET_TMP_ECDH:
|
||||||
|
@ -3759,6 +3762,9 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SSL_CTRL_SET_DH_AUTO:
|
||||||
|
ctx->cert->dh_tmp_auto = larg;
|
||||||
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_ECDH
|
#ifndef OPENSSL_NO_ECDH
|
||||||
case SSL_CTRL_SET_TMP_ECDH:
|
case SSL_CTRL_SET_TMP_ECDH:
|
||||||
|
|
|
@ -1679,7 +1679,18 @@ int ssl3_send_server_key_exchange(SSL *s)
|
||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
if (type & SSL_kDHE)
|
if (type & SSL_kDHE)
|
||||||
{
|
{
|
||||||
dhp=cert->dh_tmp;
|
if (s->cert->dh_tmp_auto)
|
||||||
|
{
|
||||||
|
dhp = ssl_get_auto_dh(s);
|
||||||
|
if (dhp == NULL)
|
||||||
|
{
|
||||||
|
al=SSL_AD_INTERNAL_ERROR;
|
||||||
|
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
|
||||||
|
goto f_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dhp=cert->dh_tmp;
|
||||||
if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
|
if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
|
||||||
dhp=s->cert->dh_tmp_cb(s,
|
dhp=s->cert->dh_tmp_cb(s,
|
||||||
SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
|
SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
|
||||||
|
@ -1697,7 +1708,9 @@ int ssl3_send_server_key_exchange(SSL *s)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dh=DHparams_dup(dhp)) == NULL)
|
if (s->cert->dh_tmp_auto)
|
||||||
|
dh = dhp;
|
||||||
|
else if ((dh=DHparams_dup(dhp)) == NULL)
|
||||||
{
|
{
|
||||||
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
|
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -1957,6 +1957,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
|
||||||
#define SSL_CERT_SET_NEXT 2
|
#define SSL_CERT_SET_NEXT 2
|
||||||
#define SSL_CERT_SET_SERVER 3
|
#define SSL_CERT_SET_SERVER 3
|
||||||
|
|
||||||
|
#define SSL_CTRL_SET_DH_AUTO 118
|
||||||
|
|
||||||
#define DTLSv1_get_timeout(ssl, arg) \
|
#define DTLSv1_get_timeout(ssl, arg) \
|
||||||
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
|
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
|
||||||
#define DTLSv1_handle_timeout(ssl) \
|
#define DTLSv1_handle_timeout(ssl) \
|
||||||
|
@ -1982,6 +1984,11 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
|
||||||
#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
|
#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
|
||||||
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
|
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
|
||||||
|
|
||||||
|
#define SSL_CTX_set_dh_auto(ctx, onoff) \
|
||||||
|
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
|
||||||
|
#define SSL_set_dh_auto(s, onoff) \
|
||||||
|
SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
|
||||||
|
|
||||||
#define SSL_need_tmp_RSA(ssl) \
|
#define SSL_need_tmp_RSA(ssl) \
|
||||||
SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
|
SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL)
|
||||||
#define SSL_set_tmp_rsa(ssl,rsa) \
|
#define SSL_set_tmp_rsa(ssl,rsa) \
|
||||||
|
|
|
@ -257,6 +257,7 @@ CERT *ssl_cert_dup(CERT *cert)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret->dh_tmp_cb = cert->dh_tmp_cb;
|
ret->dh_tmp_cb = cert->dh_tmp_cb;
|
||||||
|
ret->dh_tmp_auto = cert->dh_tmp_auto;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ECDH
|
#ifndef OPENSSL_NO_ECDH
|
||||||
|
|
|
@ -2353,8 +2353,8 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
|
||||||
rsa_tmp=rsa_tmp_export=0;
|
rsa_tmp=rsa_tmp_export=0;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
|
dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL || c->dh_tmp_auto);
|
||||||
dh_tmp_export=(c->dh_tmp_cb != NULL ||
|
dh_tmp_export= !c->dh_tmp_auto && (c->dh_tmp_cb != NULL ||
|
||||||
(dh_tmp && DH_size(c->dh_tmp)*8 <= kl));
|
(dh_tmp && DH_size(c->dh_tmp)*8 <= kl));
|
||||||
#else
|
#else
|
||||||
dh_tmp=dh_tmp_export=0;
|
dh_tmp=dh_tmp_export=0;
|
||||||
|
|
|
@ -557,6 +557,7 @@ typedef struct cert_st
|
||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
DH *dh_tmp;
|
DH *dh_tmp;
|
||||||
DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
|
DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
|
||||||
|
int dh_tmp_auto;
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_ECDH
|
#ifndef OPENSSL_NO_ECDH
|
||||||
EC_KEY *ecdh_tmp;
|
EC_KEY *ecdh_tmp;
|
||||||
|
@ -1310,6 +1311,9 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
|
||||||
int idx);
|
int idx);
|
||||||
void tls1_set_cert_validity(SSL *s);
|
void tls1_set_cert_validity(SSL *s);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifndef OPENSSL_NO_DH
|
||||||
|
DH *ssl_get_auto_dh(SSL *s);
|
||||||
#endif
|
#endif
|
||||||
EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
|
EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
|
||||||
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
|
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
|
||||||
|
|
48
ssl/t1_lib.c
48
ssl/t1_lib.c
|
@ -115,6 +115,10 @@
|
||||||
#include <openssl/hmac.h>
|
#include <openssl/hmac.h>
|
||||||
#include <openssl/ocsp.h>
|
#include <openssl/ocsp.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
#ifndef OPENSSL_NO_DH
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#endif
|
||||||
#include "ssl_locl.h"
|
#include "ssl_locl.h"
|
||||||
|
|
||||||
const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
|
const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
|
||||||
|
@ -4439,3 +4443,47 @@ int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_DH
|
||||||
|
DH *ssl_get_auto_dh(SSL *s)
|
||||||
|
{
|
||||||
|
int dh_secbits = 80;
|
||||||
|
if (s->cert->dh_tmp_auto == 2)
|
||||||
|
return DH_get_1024_160();
|
||||||
|
if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
||||||
|
{
|
||||||
|
if (s->s3->tmp.new_cipher->strength_bits == 256)
|
||||||
|
dh_secbits = 128;
|
||||||
|
else
|
||||||
|
dh_secbits = 80;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CERT_PKEY *cpk = ssl_get_server_send_pkey(s);
|
||||||
|
dh_secbits = EVP_PKEY_security_bits(cpk->privatekey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dh_secbits >= 128)
|
||||||
|
{
|
||||||
|
DH *dhp = DH_new();
|
||||||
|
if (!dhp)
|
||||||
|
return NULL;
|
||||||
|
dhp->g = BN_new();
|
||||||
|
if (dhp->g)
|
||||||
|
BN_set_word(dhp->g, 2);
|
||||||
|
if (dh_secbits >= 192)
|
||||||
|
dhp->p = get_rfc3526_prime_8192(NULL);
|
||||||
|
else
|
||||||
|
dhp->p = get_rfc3526_prime_3072(NULL);
|
||||||
|
if (!dhp->p || !dhp->g)
|
||||||
|
{
|
||||||
|
DH_free(dhp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return dhp;
|
||||||
|
}
|
||||||
|
if (dh_secbits >= 112)
|
||||||
|
return DH_get_2048_224();
|
||||||
|
return DH_get_1024_160();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue