1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-10 06:47:55 -08:00

Add support for automatic DH ephemeral keys.

This allows an SSL server to enable DHE ciphers with a single setting,
which results in an DH key being generated based on the server key length.

Partly based on OpenSSL.
This commit is contained in:
jsing 2014-10-31 15:25:55 +00:00
parent 12ce7bf06c
commit 95986511df
12 changed files with 194 additions and 44 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: s3_lib.c,v 1.83 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: s3_lib.c,v 1.84 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1994,13 +1994,15 @@ ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
ret = 1;
}
break;
case SSL_CTRL_SET_TMP_DH_CB:
{
SSLerr(SSL_F_SSL3_CTRL,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (ret);
}
break;
SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (ret);
case SSL_CTRL_SET_DH_AUTO:
s->cert->dh_tmp_auto = larg;
return 1;
case SSL_CTRL_SET_TMP_ECDH:
{
EC_KEY *ecdh = NULL;
@ -2183,13 +2185,15 @@ ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return 1;
}
/*break; */
case SSL_CTRL_SET_TMP_DH_CB:
{
SSLerr(SSL_F_SSL3_CTX_CTRL,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (0);
}
break;
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (0);
case SSL_CTRL_SET_DH_AUTO:
ctx->cert->dh_tmp_auto = larg;
return (1);
case SSL_CTRL_SET_TMP_ECDH:
{
EC_KEY *ecdh = NULL;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: s3_srvr.c,v 1.88 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: s3_srvr.c,v 1.89 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1360,10 +1360,21 @@ ssl3_send_server_key_exchange(SSL *s)
r[0] = r[1] = r[2] = r[3] = NULL;
n = 0;
if (type & SSL_kDHE) {
dhp = cert->dh_tmp;
if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
if (s->cert->dh_tmp_auto != 0) {
if ((dhp = ssl_get_auto_dh(s)) == 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)
dhp = s->cert->dh_tmp_cb(s, 0,
SSL_C_PKEYLENGTH(s->s3->tmp.new_cipher));
if (dhp == NULL) {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
@ -1377,7 +1388,9 @@ ssl3_send_server_key_exchange(SSL *s)
goto err;
}
if ((dh = DHparams_dup(dhp)) == NULL) {
if (s->cert->dh_tmp_auto != 0) {
dh = dhp;
} else if ((dh = DHparams_dup(dhp)) == NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
ERR_R_DH_LIB);
goto err;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: s3_lib.c,v 1.83 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: s3_lib.c,v 1.84 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1994,13 +1994,15 @@ ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
ret = 1;
}
break;
case SSL_CTRL_SET_TMP_DH_CB:
{
SSLerr(SSL_F_SSL3_CTRL,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (ret);
}
break;
SSLerr(SSL_F_SSL3_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (ret);
case SSL_CTRL_SET_DH_AUTO:
s->cert->dh_tmp_auto = larg;
return 1;
case SSL_CTRL_SET_TMP_ECDH:
{
EC_KEY *ecdh = NULL;
@ -2183,13 +2185,15 @@ ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return 1;
}
/*break; */
case SSL_CTRL_SET_TMP_DH_CB:
{
SSLerr(SSL_F_SSL3_CTX_CTRL,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (0);
}
break;
SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (0);
case SSL_CTRL_SET_DH_AUTO:
ctx->cert->dh_tmp_auto = larg;
return (1);
case SSL_CTRL_SET_TMP_ECDH:
{
EC_KEY *ecdh = NULL;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: s3_srvr.c,v 1.88 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: s3_srvr.c,v 1.89 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1360,10 +1360,21 @@ ssl3_send_server_key_exchange(SSL *s)
r[0] = r[1] = r[2] = r[3] = NULL;
n = 0;
if (type & SSL_kDHE) {
dhp = cert->dh_tmp;
if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
if (s->cert->dh_tmp_auto != 0) {
if ((dhp = ssl_get_auto_dh(s)) == 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)
dhp = s->cert->dh_tmp_cb(s, 0,
SSL_C_PKEYLENGTH(s->s3->tmp.new_cipher));
if (dhp == NULL) {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
@ -1377,7 +1388,9 @@ ssl3_send_server_key_exchange(SSL *s)
goto err;
}
if ((dh = DHparams_dup(dhp)) == NULL) {
if (s->cert->dh_tmp_auto != 0) {
dh = dhp;
} else if ((dh = DHparams_dup(dhp)) == NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,
ERR_R_DH_LIB);
goto err;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl.h,v 1.68 2014/10/15 13:57:21 jsing Exp $ */
/* $OpenBSD: ssl.h,v 1.69 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1429,6 +1429,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_ECDH_AUTO 94
#define SSL_CTRL_SET_DH_AUTO 118
#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
#define DTLSv1_handle_timeout(ssl) \
@ -1453,6 +1455,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
#define SSL_CTX_set_tmp_ecdh(ctx,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_CTX_set_ecdh_auto(ctx, onoff) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)
@ -1464,6 +1468,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
#define SSL_set_tmp_ecdh(ssl,ecdh) \
SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
#define SSL_set_dh_auto(s, onoff) \
SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
#define SSL_set_ecdh_auto(s, onoff) \
SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_cert.c,v 1.43 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: ssl_cert.c,v 1.44 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -229,6 +229,7 @@ ssl_cert_dup(CERT *cert)
}
}
ret->dh_tmp_cb = cert->dh_tmp_cb;
ret->dh_tmp_auto = cert->dh_tmp_auto;
if (cert->ecdh_tmp) {
ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_lib.c,v 1.88 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: ssl_lib.c,v 1.89 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1942,7 +1942,8 @@ ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
if (c == NULL)
return;
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 != 0);
have_ecdh_tmp = (c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL ||
c->ecdh_tmp_auto != 0);
@ -2176,6 +2177,54 @@ ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, const EVP_MD **pmd)
return (c->pkeys[idx].privatekey);
}
DH *
ssl_get_auto_dh(SSL *s)
{
CERT_PKEY *cpk;
int keylen;
DH *dhp;
if (s->cert->dh_tmp_auto == 2) {
keylen = 1024;
} else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) {
keylen = 1024;
if (s->s3->tmp.new_cipher->strength_bits == 256)
keylen = 3072;
} else {
if ((cpk = ssl_get_server_send_pkey(s)) == NULL)
return (NULL);
if (cpk->privatekey == NULL || cpk->privatekey->pkey.dh == NULL)
return (NULL);
keylen = EVP_PKEY_bits(cpk->privatekey);
}
if ((dhp = DH_new()) == NULL)
return (NULL);
dhp->g = BN_new();
if (dhp->g != NULL)
BN_set_word(dhp->g, 2);
if (keylen >= 8192)
dhp->p = get_rfc3526_prime_8192(NULL);
else if (keylen >= 4096)
dhp->p = get_rfc3526_prime_4096(NULL);
else if (keylen >= 3072)
dhp->p = get_rfc3526_prime_3072(NULL);
else if (keylen >= 2048)
dhp->p = get_rfc3526_prime_2048(NULL);
else if (keylen >= 1536)
dhp->p = get_rfc3526_prime_1536(NULL);
else
dhp->p = get_rfc2409_prime_1024(NULL);
if (dhp->p == NULL || dhp->g == NULL) {
DH_free(dhp);
return (NULL);
}
return (dhp);
}
void
ssl_update_cache(SSL *s, int mode)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_locl.h,v 1.72 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: ssl_locl.h,v 1.73 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -442,6 +442,7 @@ typedef struct cert_st {
DH *dh_tmp;
DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize);
int dh_tmp_auto;
EC_KEY *ecdh_tmp;
EC_KEY *(*ecdh_tmp_cb)(SSL *ssl, int is_export, int keysize);
@ -588,6 +589,7 @@ int ssl_undefined_const_function(const SSL *s);
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
X509 *ssl_get_server_send_cert(const SSL *);
EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c, const EVP_MD **pmd);
DH *ssl_get_auto_dh(SSL *s);
int ssl_cert_type(X509 *x, EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl.h,v 1.68 2014/10/15 13:57:21 jsing Exp $ */
/* $OpenBSD: ssl.h,v 1.69 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1429,6 +1429,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_ECDH_AUTO 94
#define SSL_CTRL_SET_DH_AUTO 118
#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
#define DTLSv1_handle_timeout(ssl) \
@ -1453,6 +1455,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
#define SSL_CTX_set_tmp_ecdh(ctx,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_CTX_set_ecdh_auto(ctx, onoff) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)
@ -1464,6 +1468,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh)
#define SSL_set_tmp_ecdh(ssl,ecdh) \
SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh)
#define SSL_set_dh_auto(s, onoff) \
SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
#define SSL_set_ecdh_auto(s, onoff) \
SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_cert.c,v 1.43 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: ssl_cert.c,v 1.44 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -229,6 +229,7 @@ ssl_cert_dup(CERT *cert)
}
}
ret->dh_tmp_cb = cert->dh_tmp_cb;
ret->dh_tmp_auto = cert->dh_tmp_auto;
if (cert->ecdh_tmp) {
ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_lib.c,v 1.88 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: ssl_lib.c,v 1.89 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -1942,7 +1942,8 @@ ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
if (c == NULL)
return;
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 != 0);
have_ecdh_tmp = (c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL ||
c->ecdh_tmp_auto != 0);
@ -2176,6 +2177,54 @@ ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, const EVP_MD **pmd)
return (c->pkeys[idx].privatekey);
}
DH *
ssl_get_auto_dh(SSL *s)
{
CERT_PKEY *cpk;
int keylen;
DH *dhp;
if (s->cert->dh_tmp_auto == 2) {
keylen = 1024;
} else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) {
keylen = 1024;
if (s->s3->tmp.new_cipher->strength_bits == 256)
keylen = 3072;
} else {
if ((cpk = ssl_get_server_send_pkey(s)) == NULL)
return (NULL);
if (cpk->privatekey == NULL || cpk->privatekey->pkey.dh == NULL)
return (NULL);
keylen = EVP_PKEY_bits(cpk->privatekey);
}
if ((dhp = DH_new()) == NULL)
return (NULL);
dhp->g = BN_new();
if (dhp->g != NULL)
BN_set_word(dhp->g, 2);
if (keylen >= 8192)
dhp->p = get_rfc3526_prime_8192(NULL);
else if (keylen >= 4096)
dhp->p = get_rfc3526_prime_4096(NULL);
else if (keylen >= 3072)
dhp->p = get_rfc3526_prime_3072(NULL);
else if (keylen >= 2048)
dhp->p = get_rfc3526_prime_2048(NULL);
else if (keylen >= 1536)
dhp->p = get_rfc3526_prime_1536(NULL);
else
dhp->p = get_rfc2409_prime_1024(NULL);
if (dhp->p == NULL || dhp->g == NULL) {
DH_free(dhp);
return (NULL);
}
return (dhp);
}
void
ssl_update_cache(SSL *s, int mode)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_locl.h,v 1.72 2014/10/31 14:51:01 jsing Exp $ */
/* $OpenBSD: ssl_locl.h,v 1.73 2014/10/31 15:25:55 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -442,6 +442,7 @@ typedef struct cert_st {
DH *dh_tmp;
DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize);
int dh_tmp_auto;
EC_KEY *ecdh_tmp;
EC_KEY *(*ecdh_tmp_cb)(SSL *ssl, int is_export, int keysize);
@ -588,6 +589,7 @@ int ssl_undefined_const_function(const SSL *s);
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
X509 *ssl_get_server_send_cert(const SSL *);
EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c, const EVP_MD **pmd);
DH *ssl_get_auto_dh(SSL *s);
int ssl_cert_type(X509 *x, EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);