mirror of
https://github.com/openssl/openssl.git
synced 2024-11-28 04:25:31 +08:00
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.
This commit is contained in:
parent
2131ce570a
commit
a43526302f
7
CHANGES
7
CHANGES
@ -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];
|
||||
|
84
ssl/t1_lib.c
84
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
|
||||
* 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)
|
||||
|
Loading…
Reference in New Issue
Block a user