提交 a4352630 编写于 作者: D Dr. Stephen Henson

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.
上级 2131ce57
......@@ -4,6 +4,13 @@
Changes between 1.0.1 and 1.1.0 [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
static structures instead of allocation if default values are used.
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);
BIO_printf(out, "%s", cname);
}
if (ncurves == 0)
BIO_puts(out, "NONE");
BIO_puts(out, "\n");
return 1;
}
......
......@@ -1713,10 +1713,11 @@ bad:
{
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)
{
BIO_printf(bio_err, "unknown curve name (%s)\n",
......@@ -1736,6 +1737,8 @@ bad:
{
BIO_printf(bio_s_out,"Setting temp ECDH parameters\n");
}
else if (named_curve)
SSL_CTX_set_ecdh_auto(ctx, 1);
else
{
BIO_printf(bio_s_out,"Using default temp ECDH parameters\n");
......
......@@ -3398,7 +3398,10 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_GET_SHARED_CURVE:
return tls1_shared_curve(s, larg);
case SSL_CTRL_SET_ECDH_AUTO:
s->cert->ecdh_tmp_auto = larg;
break;
default:
break;
......@@ -3678,6 +3681,9 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return tls1_set_curves_list(&ctx->tlsext_ellipticcurvelist,
&ctx->tlsext_ellipticcurvelist_length,
parg);
case SSL_CTRL_SET_ECDH_AUTO:
ctx->cert->ecdh_tmp_auto = larg;
break;
#endif /* !OPENSSL_NO_TLSEXT */
/* A Thawte special :-) */
......
......@@ -1683,7 +1683,14 @@ int ssl3_send_server_key_exchange(SSL *s)
const EC_GROUP *group;
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,
SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
......@@ -1708,7 +1715,9 @@ int ssl3_send_server_key_exchange(SSL *s)
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
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);
goto err;
......
......@@ -1629,6 +1629,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_CURVES 91
#define SSL_CTRL_SET_CURVES_LIST 92
#define SSL_CTRL_GET_SHARED_CURVE 93
#define SSL_CTRL_SET_ECDH_AUTO 94
#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
......@@ -1700,6 +1701,10 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s)
#define SSL_get_shared_curve(s, n) \
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
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_auto = cert->ecdh_tmp_auto;
#endif
for (i = 0; i < SSL_PKEY_NUM; i++)
......
......@@ -2072,7 +2072,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
#endif
#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
cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
rsa_enc= (cpk->x509 != NULL && cpk->privatekey != NULL);
......
......@@ -502,6 +502,8 @@ typedef struct cert_st
EC_KEY *ecdh_tmp;
/* Callback for generating ephemeral ECDH keys */
EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
/* Select ECDH parameters automatically */
int ecdh_tmp_auto;
#endif
CERT_PKEY pkeys[SSL_PKEY_NUM];
......
......@@ -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
* preference list where we return the most preferred match.
/* Return nth shared curve. If nmatch == -1 return number of
* matches.
*/
int tls1_shared_list(SSL *s,
const unsigned char *l1, size_t l1len,
const unsigned char *l2, size_t l2len,
int nmatch)
int tls1_shared_curve(SSL *s, int nmatch)
{
const unsigned char *pref, *supp;
size_t preflen, supplen, i, j;
int k;
l1len /= 2;
l2len /= 2;
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
{
pref = l1;
preflen = l1len;
supp = l2;
supplen = l2len;
}
else
{
supp = l1;
supplen = l1len;
pref = l2;
preflen = l2len;
}
/* Can't do anything on client side */
if (s->server == 0)
return -1;
tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
&supp, &supplen);
tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
&pref, &preflen);
preflen /= 2;
supplen /= 2;
k = 0;
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 (nmatch == k)
return (pref[0] << 8) | pref[1];
{
int id = (pref[0] << 8) | pref[1];
return tls1_ec_curve_id2nid(id);
}
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)
return id;
return tls1_ec_curve_id2nid(id);
return k;
return 0;
}
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;
size_t plen, i;
int j;
/* If point formats extension present check it, otherwise everything
* is supported (see RFC4492).
*/
......@@ -546,19 +523,17 @@ static int tls1_check_ec_key(SSL *s,
if (i == plen)
return 0;
}
/* If curve list present check it, otherwise everything is
* supported.
*/
if (s->session->tlsext_ellipticcurvelist)
/* Check curve is consistent with client and server preferences */
for (j = 0; j <= 1; j++)
{
p = s->session->tlsext_ellipticcurvelist;
plen = s->session->tlsext_ellipticcurvelist_length;
tls1_get_curvelist(s, j, &p, &plen);
for (i = 0; i < plen; i+=2, p+=2)
{
if (p[0] == curve_id[0] && p[1] == curve_id[1])
return 1;
break;
}
return 0;
if (i == plen)
return 0;
}
return 1;
}
......@@ -585,6 +560,13 @@ int tls1_check_ec_tmp_key(SSL *s)
{
unsigned char curve_id[2];
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 (s->cert->ecdh_tmp_cb)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册