Add support for automatic ECDH temporary key parameter selection. When
enabled instead of requiring an application to hard code a (possibly inappropriate) parameter set and delve into EC internals we just automatically use the preferred curve. (backport from HEAD)
This commit is contained in:
parent
c132ca95c0
commit
e46c807e4f
7
CHANGES
7
CHANGES
@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
Changes between 1.0.1 and 1.0.2 [xx XXX xxxx]
|
Changes between 1.0.1 and 1.0.2 [xx XXX xxxx]
|
||||||
|
|
||||||
|
*) Support for automatic EC temporary key parameter selection. If enabled
|
||||||
|
the most preferred EC parameters are automatically used instead of
|
||||||
|
hardcoded fixed parameters. Now a server just has to call:
|
||||||
|
SSL_CTX_set_ecdh_auto(ctx, 1) and the server will automatically
|
||||||
|
support ECDH and use the most appropriate parameters.
|
||||||
|
[Steve Henson]
|
||||||
|
|
||||||
*) Enhance and tidy EC curve and point format TLS extension code. Use
|
*) Enhance and tidy EC curve and point format TLS extension code. Use
|
||||||
static structures instead of allocation if default values are used.
|
static structures instead of allocation if default values are used.
|
||||||
New ctrls to set curves we wish to support and to retrieve shared curves.
|
New ctrls to set curves we wish to support and to retrieve shared curves.
|
||||||
|
@ -355,6 +355,8 @@ int ssl_print_curves(BIO *out, SSL *s)
|
|||||||
cname = OBJ_nid2sn(nid);
|
cname = OBJ_nid2sn(nid);
|
||||||
BIO_printf(out, "%s", cname);
|
BIO_printf(out, "%s", cname);
|
||||||
}
|
}
|
||||||
|
if (ncurves == 0)
|
||||||
|
BIO_puts(out, "NONE");
|
||||||
BIO_puts(out, "\n");
|
BIO_puts(out, "\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1693,10 +1693,11 @@ bad:
|
|||||||
{
|
{
|
||||||
EC_KEY *ecdh=NULL;
|
EC_KEY *ecdh=NULL;
|
||||||
|
|
||||||
if (named_curve)
|
if (named_curve && strcmp(named_curve, "auto"))
|
||||||
{
|
{
|
||||||
int nid = OBJ_sn2nid(named_curve);
|
int nid = EC_curve_nist2nid(named_curve);
|
||||||
|
if (nid == NID_undef)
|
||||||
|
nid = OBJ_sn2nid(named_curve);
|
||||||
if (nid == 0)
|
if (nid == 0)
|
||||||
{
|
{
|
||||||
BIO_printf(bio_err, "unknown curve name (%s)\n",
|
BIO_printf(bio_err, "unknown curve name (%s)\n",
|
||||||
@ -1716,6 +1717,8 @@ bad:
|
|||||||
{
|
{
|
||||||
BIO_printf(bio_s_out,"Setting temp ECDH parameters\n");
|
BIO_printf(bio_s_out,"Setting temp ECDH parameters\n");
|
||||||
}
|
}
|
||||||
|
else if (named_curve)
|
||||||
|
SSL_CTX_set_ecdh_auto(ctx, 1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BIO_printf(bio_s_out,"Using default temp ECDH parameters\n");
|
BIO_printf(bio_s_out,"Using default temp ECDH parameters\n");
|
||||||
|
@ -3399,6 +3399,9 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
|
|||||||
case SSL_CTRL_GET_SHARED_CURVE:
|
case SSL_CTRL_GET_SHARED_CURVE:
|
||||||
return tls1_shared_curve(s, larg);
|
return tls1_shared_curve(s, larg);
|
||||||
|
|
||||||
|
case SSL_CTRL_SET_ECDH_AUTO:
|
||||||
|
s->cert->ecdh_tmp_auto = larg;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -3673,6 +3676,9 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
|
|||||||
return tls1_set_curves_list(&ctx->tlsext_ellipticcurvelist,
|
return tls1_set_curves_list(&ctx->tlsext_ellipticcurvelist,
|
||||||
&ctx->tlsext_ellipticcurvelist_length,
|
&ctx->tlsext_ellipticcurvelist_length,
|
||||||
parg);
|
parg);
|
||||||
|
case SSL_CTRL_SET_ECDH_AUTO:
|
||||||
|
ctx->cert->ecdh_tmp_auto = larg;
|
||||||
|
break;
|
||||||
#endif /* !OPENSSL_NO_TLSEXT */
|
#endif /* !OPENSSL_NO_TLSEXT */
|
||||||
|
|
||||||
/* A Thawte special :-) */
|
/* A Thawte special :-) */
|
||||||
|
@ -1673,7 +1673,14 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|||||||
const EC_GROUP *group;
|
const EC_GROUP *group;
|
||||||
|
|
||||||
ecdhp=cert->ecdh_tmp;
|
ecdhp=cert->ecdh_tmp;
|
||||||
if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
|
if (s->cert->ecdh_tmp_auto)
|
||||||
|
{
|
||||||
|
/* Get NID of first shared curve */
|
||||||
|
int nid = tls1_shared_curve(s, 0);
|
||||||
|
if (nid != NID_undef)
|
||||||
|
ecdhp = EC_KEY_new_by_curve_name(nid);
|
||||||
|
}
|
||||||
|
else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb)
|
||||||
{
|
{
|
||||||
ecdhp=s->cert->ecdh_tmp_cb(s,
|
ecdhp=s->cert->ecdh_tmp_cb(s,
|
||||||
SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
|
SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
|
||||||
@ -1698,7 +1705,9 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|||||||
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
|
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
|
if (s->cert->ecdh_tmp_auto)
|
||||||
|
ecdh = ecdhp;
|
||||||
|
else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
|
||||||
{
|
{
|
||||||
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
|
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1619,6 +1619,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
|
|||||||
#define SSL_CTRL_SET_CURVES 91
|
#define SSL_CTRL_SET_CURVES 91
|
||||||
#define SSL_CTRL_SET_CURVES_LIST 92
|
#define SSL_CTRL_SET_CURVES_LIST 92
|
||||||
#define SSL_CTRL_GET_SHARED_CURVE 93
|
#define SSL_CTRL_GET_SHARED_CURVE 93
|
||||||
|
#define SSL_CTRL_SET_ECDH_AUTO 94
|
||||||
|
|
||||||
#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)
|
||||||
@ -1690,6 +1691,10 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
|
|||||||
SSL_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s)
|
SSL_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s)
|
||||||
#define SSL_get_shared_curve(s, n) \
|
#define SSL_get_shared_curve(s, n) \
|
||||||
SSL_ctrl(s,SSL_CTRL_GET_SHARED_CURVE,n,NULL)
|
SSL_ctrl(s,SSL_CTRL_GET_SHARED_CURVE,n,NULL)
|
||||||
|
#define SSL_CTX_set_ecdh_auto(ctx, onoff) \
|
||||||
|
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)
|
||||||
|
#define SSL_set_ecdh_auto(s, onoff) \
|
||||||
|
SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL)
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_BIO
|
#ifndef OPENSSL_NO_BIO
|
||||||
BIO_METHOD *BIO_f_ssl(void);
|
BIO_METHOD *BIO_f_ssl(void);
|
||||||
|
@ -270,6 +270,7 @@ CERT *ssl_cert_dup(CERT *cert)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
|
ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
|
||||||
|
ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < SSL_PKEY_NUM; i++)
|
for (i = 0; i < SSL_PKEY_NUM; i++)
|
||||||
|
@ -2069,7 +2069,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ECDH
|
#ifndef OPENSSL_NO_ECDH
|
||||||
have_ecdh_tmp=(c->ecdh_tmp != NULL || c->ecdh_tmp_cb != NULL);
|
have_ecdh_tmp=(c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
|
||||||
#endif
|
#endif
|
||||||
cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
|
cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
|
||||||
rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL);
|
rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL);
|
||||||
|
@ -504,6 +504,8 @@ typedef struct cert_st
|
|||||||
EC_KEY *ecdh_tmp;
|
EC_KEY *ecdh_tmp;
|
||||||
/* Callback for generating ephemeral ECDH keys */
|
/* Callback for generating ephemeral ECDH keys */
|
||||||
EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
|
EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
|
||||||
|
/* Select ECDH parameters automatically */
|
||||||
|
int ecdh_tmp_auto;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CERT_PKEY pkeys[SSL_PKEY_NUM];
|
CERT_PKEY pkeys[SSL_PKEY_NUM];
|
||||||
|
82
ssl/t1_lib.c
82
ssl/t1_lib.c
@ -332,33 +332,24 @@ static void tls1_get_curvelist(SSL *s, int sess,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return any common values from two lists. One list is used as a
|
/* Return nth shared curve. If nmatch == -1 return number of
|
||||||
* preference list where we return the most preferred match.
|
* matches.
|
||||||
*/
|
*/
|
||||||
int tls1_shared_list(SSL *s,
|
|
||||||
const unsigned char *l1, size_t l1len,
|
int tls1_shared_curve(SSL *s, int nmatch)
|
||||||
const unsigned char *l2, size_t l2len,
|
|
||||||
int nmatch)
|
|
||||||
{
|
{
|
||||||
const unsigned char *pref, *supp;
|
const unsigned char *pref, *supp;
|
||||||
size_t preflen, supplen, i, j;
|
size_t preflen, supplen, i, j;
|
||||||
int k;
|
int k;
|
||||||
l1len /= 2;
|
/* Can't do anything on client side */
|
||||||
l2len /= 2;
|
if (s->server == 0)
|
||||||
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
|
return -1;
|
||||||
{
|
tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
|
||||||
pref = l1;
|
&supp, &supplen);
|
||||||
preflen = l1len;
|
tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
|
||||||
supp = l2;
|
&pref, &preflen);
|
||||||
supplen = l2len;
|
preflen /= 2;
|
||||||
}
|
supplen /= 2;
|
||||||
else
|
|
||||||
{
|
|
||||||
supp = l1;
|
|
||||||
supplen = l1len;
|
|
||||||
pref = l2;
|
|
||||||
preflen = l2len;
|
|
||||||
}
|
|
||||||
k = 0;
|
k = 0;
|
||||||
for (i = 0; i < preflen; i++, pref+=2)
|
for (i = 0; i < preflen; i++, pref+=2)
|
||||||
{
|
{
|
||||||
@ -368,32 +359,17 @@ int tls1_shared_list(SSL *s,
|
|||||||
if (pref[0] == tsupp[0] && pref[1] == tsupp[1])
|
if (pref[0] == tsupp[0] && pref[1] == tsupp[1])
|
||||||
{
|
{
|
||||||
if (nmatch == k)
|
if (nmatch == k)
|
||||||
return (pref[0] << 8) | pref[1];
|
{
|
||||||
|
int id = (pref[0] << 8) | pref[1];
|
||||||
|
return tls1_ec_curve_id2nid(id);
|
||||||
|
}
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nmatch == -1 && k > 0)
|
|
||||||
return k;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tls1_shared_curve(SSL *s, int nmatch)
|
|
||||||
{
|
|
||||||
const unsigned char *l1, *l2;
|
|
||||||
size_t l1len, l2len;
|
|
||||||
int id;
|
|
||||||
/* Can't do anything on client side */
|
|
||||||
if (s->server == 0)
|
|
||||||
return -1;
|
|
||||||
/* Get supported curves */
|
|
||||||
tls1_get_curvelist(s, 0, &l1, &l1len);
|
|
||||||
tls1_get_curvelist(s, 1, &l2, &l2len);
|
|
||||||
|
|
||||||
id = tls1_shared_list(s, l1, l1len, l2, l2len, nmatch);
|
|
||||||
if (nmatch == -1)
|
if (nmatch == -1)
|
||||||
return id;
|
return k;
|
||||||
return tls1_ec_curve_id2nid(id);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tls1_set_curves(unsigned char **pext, size_t *pextlen,
|
int tls1_set_curves(unsigned char **pext, size_t *pextlen,
|
||||||
@ -531,6 +507,7 @@ static int tls1_check_ec_key(SSL *s,
|
|||||||
{
|
{
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
size_t plen, i;
|
size_t plen, i;
|
||||||
|
int j;
|
||||||
/* If point formats extension present check it, otherwise everything
|
/* If point formats extension present check it, otherwise everything
|
||||||
* is supported (see RFC4492).
|
* is supported (see RFC4492).
|
||||||
*/
|
*/
|
||||||
@ -546,18 +523,16 @@ static int tls1_check_ec_key(SSL *s,
|
|||||||
if (i == plen)
|
if (i == plen)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* If curve list present check it, otherwise everything is
|
/* Check curve is consistent with client and server preferences */
|
||||||
* supported.
|
for (j = 0; j <= 1; j++)
|
||||||
*/
|
|
||||||
if (s->session->tlsext_ellipticcurvelist)
|
|
||||||
{
|
{
|
||||||
p = s->session->tlsext_ellipticcurvelist;
|
tls1_get_curvelist(s, j, &p, &plen);
|
||||||
plen = s->session->tlsext_ellipticcurvelist_length;
|
|
||||||
for (i = 0; i < plen; i+=2, p+=2)
|
for (i = 0; i < plen; i+=2, p+=2)
|
||||||
{
|
{
|
||||||
if (p[0] == curve_id[0] && p[1] == curve_id[1])
|
if (p[0] == curve_id[0] && p[1] == curve_id[1])
|
||||||
return 1;
|
break;
|
||||||
}
|
}
|
||||||
|
if (i == plen)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -585,6 +560,13 @@ int tls1_check_ec_tmp_key(SSL *s)
|
|||||||
{
|
{
|
||||||
unsigned char curve_id[2];
|
unsigned char curve_id[2];
|
||||||
EC_KEY *ec = s->cert->ecdh_tmp;
|
EC_KEY *ec = s->cert->ecdh_tmp;
|
||||||
|
if (s->cert->ecdh_tmp_auto)
|
||||||
|
{
|
||||||
|
/* Need a shared curve */
|
||||||
|
if (tls1_shared_curve(s, 0))
|
||||||
|
return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
if (!ec)
|
if (!ec)
|
||||||
{
|
{
|
||||||
if (s->cert->ecdh_tmp_cb)
|
if (s->cert->ecdh_tmp_cb)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user