Initial revision of ECC extension handling.

Tidy some code up.

Don't allocate a structure to handle ECC extensions when it is used for
default values.

Make supported curves configurable.

Add ctrls to retrieve shared curves: not fully integrated with rest of
ECC code yet.
This commit is contained in:
Dr. Stephen Henson 2012-03-28 15:05:04 +00:00
parent 751e26cb9b
commit d0595f170c
10 changed files with 401 additions and 135 deletions

View file

@ -4,6 +4,13 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) 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.
Print out shared curves in s_server. New options to s_server and s_client
to set list of supported curves.
[Steve Henson]
*) New ctrls to retrieve supported signature algorithms and
supported curve values as an array of NIDs. Extend openssl utility
to print out received values.

View file

@ -316,18 +316,17 @@ int ssl_print_sigalgs(BIO *out, SSL *s)
int ssl_print_curves(BIO *out, SSL *s)
{
int i, ncurves, *curves;
ncurves = SSL_get1_curvelist(s, NULL);
int i, ncurves, *curves, nid;
const char *cname;
ncurves = SSL_get1_curves(s, NULL);
if (ncurves <= 0)
return 1;
curves = OPENSSL_malloc(ncurves * sizeof(int));
SSL_get1_curvelist(s, curves);
SSL_get1_curves(s, curves);
BIO_puts(out, "Supported Elliptic Curves: ");
for (i = 0; i < ncurves; i++)
{
int nid;
const char *cname;
if (i)
BIO_puts(out, ":");
nid = curves[i];
@ -343,8 +342,20 @@ int ssl_print_curves(BIO *out, SSL *s)
BIO_printf(out, "%s", cname);
}
}
BIO_puts(out, "\n");
BIO_puts(out, "\nShared Elliptic curves: ");
OPENSSL_free(curves);
ncurves = SSL_get_shared_curve(s, -1);
for (i = 0; i < ncurves; i++)
{
if (i)
BIO_puts(out, ":");
nid = SSL_get_shared_curve(s, i);
cname = EC_curve_nid2nist(nid);
if (!cname)
cname = OBJ_nid2sn(nid);
BIO_printf(out, "%s", cname);
}
BIO_puts(out, "\n");
return 1;
}

View file

@ -601,6 +601,7 @@ int MAIN(int argc, char **argv)
#endif
#ifndef OPENSSL_NO_TLSEXT
char *servername = NULL;
char *curves=NULL;
tlsextctx tlsextcbp =
{NULL,0};
# ifndef OPENSSL_NO_NEXTPROTONEG
@ -937,6 +938,11 @@ int MAIN(int argc, char **argv)
servername= *(++argv);
/* meth=TLSv1_client_method(); */
}
else if (strcmp(*argv,"-curves") == 0)
{
if (--argc < 1) goto bad;
curves= *(++argv);
}
#endif
#ifndef OPENSSL_NO_JPAKE
else if (strcmp(*argv,"-jpake") == 0)
@ -1176,6 +1182,12 @@ bad:
}
#ifndef OPENSSL_NO_TLSEXT
if (curves != NULL)
if(!SSL_CTX_set1_curves_list(ctx,curves)) {
BIO_printf(bio_err,"error setting curve list\n");
ERR_print_errors(bio_err);
goto end;
}
if (servername != NULL)
{
tlsextcbp.biodebug = bio_err;

View file

@ -273,6 +273,7 @@ static int s_server_session_id_context = 1; /* anything will do */
static const char *s_cert_file=TEST_CERT,*s_key_file=NULL;
#ifndef OPENSSL_NO_TLSEXT
static const char *s_cert_file2=TEST_CERT2,*s_key_file2=NULL;
static char *curves=NULL;
#endif
static char *s_dcert_file=NULL,*s_dkey_file=NULL;
#ifdef FIONBIO
@ -437,6 +438,7 @@ static void s_server_init(void)
s_cert_file=TEST_CERT;
s_key_file=NULL;
#ifndef OPENSSL_NO_TLSEXT
curves=NULL;
s_cert_file2=TEST_CERT2;
s_key_file2=NULL;
ctx2=NULL;
@ -1174,6 +1176,11 @@ int MAIN(int argc, char *argv[])
goto bad;
}
}
else if (strcmp(*argv,"-curves") == 0)
{
if (--argc < 1) goto bad;
curves= *(++argv);
}
#endif
else if (strcmp(*argv,"-msg") == 0)
{ s_msg=1; }
@ -1849,6 +1856,23 @@ bad:
}
#endif
}
#ifndef OPENSSL_NO_TLSEXT
if (curves)
{
if(!SSL_CTX_set1_curves_list(ctx,curves))
{
BIO_printf(bio_err,"error setting curves list\n");
ERR_print_errors(bio_err);
goto end;
}
if(ctx2 && !SSL_CTX_set1_curves_list(ctx2,curves))
{
BIO_printf(bio_err,"error setting curves list\n");
ERR_print_errors(bio_err);
goto end;
}
}
#endif
SSL_CTX_set_verify(ctx,s_server_verify,verify_callback);
SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context,
sizeof s_server_session_id_context);

View file

@ -3365,7 +3365,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
else
return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
case SSL_CTRL_GET_CURVELIST:
case SSL_CTRL_GET_CURVES:
{
unsigned char *clist;
size_t clistlen;
@ -3391,6 +3391,20 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return (int)clistlen;
}
case SSL_CTRL_SET_CURVES:
return tls1_set_curves(&s->tlsext_ellipticcurvelist,
&s->tlsext_ellipticcurvelist_length,
parg, larg);
case SSL_CTRL_SET_CURVES_LIST:
return tls1_set_curves_list(&s->tlsext_ellipticcurvelist,
&s->tlsext_ellipticcurvelist_length,
parg);
case SSL_CTRL_GET_SHARED_CURVE:
return tls1_shared_curve(s, larg);
default:
break;
}
@ -3659,6 +3673,16 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
ctx->srp_ctx.strength=larg;
break;
#endif
case SSL_CTRL_SET_CURVES:
return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
&ctx->tlsext_ellipticcurvelist_length,
parg, larg);
case SSL_CTRL_SET_CURVES_LIST:
return tls1_set_curves_list(&ctx->tlsext_ellipticcurvelist,
&ctx->tlsext_ellipticcurvelist_length,
parg);
#endif /* !OPENSSL_NO_TLSEXT */
/* A Thawte special :-) */

View file

@ -982,6 +982,13 @@ struct ssl_ctx_st
/* Callback for disabling session caching and ticket support
* on a session basis, depending on the chosen cipher. */
int (*not_resumable_session_cb)(SSL *ssl, int is_forward_secure);
#ifndef OPENSSL_NO_EC
/* EC extension values inherited by SSL structure */
size_t tlsext_ecpointformatlist_length;
unsigned char *tlsext_ecpointformatlist;
size_t tlsext_ellipticcurvelist_length;
unsigned char *tlsext_ellipticcurvelist;
#endif /* OPENSSL_NO_EC */
};
#endif
@ -1618,7 +1625,10 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_CHAIN 88
#define SSL_CTRL_CHAIN_CERT 89
#define SSL_CTRL_GET_CURVELIST 90
#define SSL_CTRL_GET_CURVES 90
#define SSL_CTRL_SET_CURVES 91
#define SSL_CTRL_SET_CURVES_LIST 92
#define SSL_CTRL_GET_SHARED_CURVE 93
#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
@ -1678,9 +1688,18 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
#define SSL_add1_chain_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
#define SSL_get1_curvelist(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_GET_CURVELIST,0,(char *)s)
#define SSL_get1_curves(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_GET_CURVES,0,(char *)s)
#define SSL_CTX_set1_curves(ctx, clist, clistlen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURVES,clistlen,(char *)clist)
#define SSL_CTX_set1_curves_list(ctx, s) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s)
#define SSL_set1_curves(ctx, clist, clistlen) \
SSL_ctrl(ctx,SSL_CTRL_SET_CURVES,clistlen,(char *)clist)
#define SSL_set1_curves_list(ctx, s) \
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)
#ifndef OPENSSL_NO_BIO
BIO_METHOD *BIO_f_ssl(void);

View file

@ -358,6 +358,28 @@ SSL *SSL_new(SSL_CTX *ctx)
s->tlsext_ocsp_resplen = -1;
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
s->initial_ctx=ctx;
#ifndef OPENSSL_NO_EC
if (ctx->tlsext_ecpointformatlist)
{
s->tlsext_ecpointformatlist =
BUF_memdup(ctx->tlsext_ecpointformatlist,
ctx->tlsext_ecpointformatlist_length);
if (!s->tlsext_ecpointformatlist)
goto err;
s->tlsext_ecpointformatlist_length =
ctx->tlsext_ecpointformatlist_length;
}
if (ctx->tlsext_ellipticcurvelist)
{
s->tlsext_ellipticcurvelist =
BUF_memdup(ctx->tlsext_ellipticcurvelist,
ctx->tlsext_ellipticcurvelist_length);
if (!s->tlsext_ellipticcurvelist)
goto err;
s->tlsext_ellipticcurvelist_length =
ctx->tlsext_ellipticcurvelist_length;
}
#endif
# ifndef OPENSSL_NO_NEXTPROTONEG
s->next_proto_negotiated = NULL;
# endif
@ -1975,6 +1997,14 @@ void SSL_CTX_free(SSL_CTX *a)
ssl_buf_freelist_free(a->wbuf_freelist);
if (a->rbuf_freelist)
ssl_buf_freelist_free(a->rbuf_freelist);
#endif
#ifndef OPENSSL_NO_TLSEXT
# ifndef OPENSSL_NO_EC
if (a->tlsext_ecpointformatlist)
OPENSSL_free(a->tlsext_ecpointformatlist);
if (a->tlsext_ellipticcurvelist)
OPENSSL_free(a->tlsext_ellipticcurvelist);
# endif /* OPENSSL_NO_EC */
#endif
OPENSSL_free(a);

View file

@ -1102,9 +1102,18 @@ SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
#ifndef OPENSSL_NO_EC
int tls1_ec_curve_id2nid(int curve_id);
int tls1_ec_nid2curve_id(int nid);
int tls1_shared_curve(SSL *s, int nmatch);
int tls1_set_curves(unsigned char **pext, size_t *pextlen,
int *curves, size_t ncurves);
int tls1_set_curves_list(unsigned char **pext, size_t *pextlen,
const char *str);
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_TLSEXT
int tls1_shared_list(SSL *s,
const unsigned char *l1, size_t l1len,
const unsigned char *l2, size_t l2len,
int nmatch);
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit);
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit);
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);

View file

@ -393,32 +393,6 @@ int ssl_get_new_session(SSL *s, int session)
return 0;
}
}
#ifndef OPENSSL_NO_EC
if (s->tlsext_ecpointformatlist)
{
if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
if ((ss->tlsext_ecpointformatlist = OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == NULL)
{
SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
SSL_SESSION_free(ss);
return 0;
}
ss->tlsext_ecpointformatlist_length = s->tlsext_ecpointformatlist_length;
memcpy(ss->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
}
if (s->tlsext_ellipticcurvelist)
{
if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
if ((ss->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
{
SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
SSL_SESSION_free(ss);
return 0;
}
ss->tlsext_ellipticcurvelist_length = s->tlsext_ellipticcurvelist_length;
memcpy(ss->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
}
#endif
#endif
}
else

View file

@ -202,33 +202,41 @@ static int nid_list[] =
NID_secp521r1 /* secp521r1 (25) */
};
static int pref_list[] =
static const unsigned char ecformats_default[] =
{
NID_sect571r1, /* sect571r1 (14) */
NID_sect571k1, /* sect571k1 (13) */
NID_secp521r1, /* secp521r1 (25) */
NID_sect409k1, /* sect409k1 (11) */
NID_sect409r1, /* sect409r1 (12) */
NID_secp384r1, /* secp384r1 (24) */
NID_sect283k1, /* sect283k1 (9) */
NID_sect283r1, /* sect283r1 (10) */
NID_secp256k1, /* secp256k1 (22) */
NID_X9_62_prime256v1, /* secp256r1 (23) */
NID_sect239k1, /* sect239k1 (8) */
NID_sect233k1, /* sect233k1 (6) */
NID_sect233r1, /* sect233r1 (7) */
NID_secp224k1, /* secp224k1 (20) */
NID_secp224r1, /* secp224r1 (21) */
NID_sect193r1, /* sect193r1 (4) */
NID_sect193r2, /* sect193r2 (5) */
NID_secp192k1, /* secp192k1 (18) */
NID_X9_62_prime192v1, /* secp192r1 (19) */
NID_sect163k1, /* sect163k1 (1) */
NID_sect163r1, /* sect163r1 (2) */
NID_sect163r2, /* sect163r2 (3) */
NID_secp160k1, /* secp160k1 (15) */
NID_secp160r1, /* secp160r1 (16) */
NID_secp160r2, /* secp160r2 (17) */
TLSEXT_ECPOINTFORMAT_uncompressed,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime,
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
};
static const unsigned char eccurves_default[] =
{
0,14, /* sect571r1 (14) */
0,13, /* sect571k1 (13) */
0,25, /* secp521r1 (25) */
0,11, /* sect409k1 (11) */
0,12, /* sect409r1 (12) */
0,24, /* secp384r1 (24) */
0,9, /* sect283k1 (9) */
0,10, /* sect283r1 (10) */
0,22, /* secp256k1 (22) */
0,23, /* secp256r1 (23) */
0,8, /* sect239k1 (8) */
0,6, /* sect233k1 (6) */
0,7, /* sect233r1 (7) */
0,20, /* secp224k1 (20) */
0,21, /* secp224r1 (21) */
0,4, /* sect193r1 (4) */
0,5, /* sect193r2 (5) */
0,18, /* secp192k1 (18) */
0,19, /* secp192r1 (19) */
0,1, /* sect163k1 (1) */
0,2, /* sect163r1 (2) */
0,3, /* sect163r2 (3) */
0,15, /* secp160k1 (15) */
0,16, /* secp160r1 (16) */
0,17, /* secp160r2 (17) */
};
int tls1_ec_curve_id2nid(int curve_id)
@ -299,6 +307,166 @@ int tls1_ec_nid2curve_id(int nid)
return 0;
}
}
/* Return any common values from two lists. One list is used as a
* preference list where we return the most preferred match.
*/
int tls1_shared_list(SSL *s,
const unsigned char *l1, size_t l1len,
const unsigned char *l2, size_t l2len,
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;
}
k = 0;
for (i = 0; i < preflen; i++, pref+=2)
{
const unsigned char *tsupp = supp;
for (j = 0; j < supplen; j++, tsupp+=2)
{
if (pref[0] == tsupp[0] && pref[1] == tsupp[1])
{
if (nmatch == k)
return (pref[0] << 8) | pref[1];
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;
/* Use our preferred curve list, if not set use default */
if (s->tlsext_ellipticcurvelist)
{
l1 = s->tlsext_ellipticcurvelist;
l1len = s->tlsext_ellipticcurvelist_length;
}
else
{
l1 = eccurves_default;
l1len = sizeof(eccurves_default);
}
/* Use peer preferred curve list, if not set use default */
if(s->session->tlsext_ellipticcurvelist)
{
l2 = s->session->tlsext_ellipticcurvelist;
l2len =s->session->tlsext_ellipticcurvelist_length;
}
else
{
l2 = eccurves_default;
l2len = sizeof(eccurves_default);
}
id = tls1_shared_list(s, l1, l1len, l2, l2len, nmatch);
if (nmatch == -1)
return id;
return tls1_ec_curve_id2nid(id);
}
int tls1_set_curves(unsigned char **pext, size_t *pextlen,
int *curves, size_t ncurves)
{
unsigned char *clist, *p;
size_t i;
/* Bitmap of curves included to detect duplicates: only works
* while curve ids < 32
*/
unsigned long dup_list = 0;
clist = OPENSSL_malloc(ncurves * 2);
if (!clist)
return 0;
for (i = 0, p = clist; i < ncurves; i++)
{
unsigned long idmask;
int id;
id = tls1_ec_nid2curve_id(curves[i]);
idmask = 1L << id;
if (!id || (dup_list & idmask))
{
OPENSSL_free(clist);
return 0;
}
dup_list |= idmask;
s2n(id, p);
}
if (*pext)
OPENSSL_free(*pext);
*pext = clist;
*pextlen = ncurves * 2;
return 1;
}
#define MAX_CURVELIST 25
typedef struct
{
size_t nidcnt;
int nid_arr[MAX_CURVELIST];
} nid_cb_st;
static int nid_cb(const char *elem, int len, void *arg)
{
nid_cb_st *narg = arg;
size_t i;
int nid;
char etmp[20];
if (narg->nidcnt == MAX_CURVELIST)
return 0;
if (len > (int)(sizeof(etmp) - 1))
return 0;
memcpy(etmp, elem, len);
etmp[len] = 0;
nid = EC_curve_nist2nid(etmp);
if (nid == NID_undef)
nid = OBJ_sn2nid(etmp);
if (nid == NID_undef)
nid = OBJ_ln2nid(etmp);
if (nid == NID_undef)
return 0;
for (i = 0; i < narg->nidcnt; i++)
if (narg->nid_arr[i] == nid)
return 0;
narg->nid_arr[narg->nidcnt++] = nid;
return 1;
}
/* Set curves based on a colon separate list */
int tls1_set_curves_list(unsigned char **pext, size_t *pextlen,
const char *str)
{
nid_cb_st ncb;
ncb.nidcnt = 0;
if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb))
return 0;
return tls1_set_curves(pext, pextlen, ncb.nid_arr, ncb.nidcnt);
}
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_TLSEXT
@ -364,6 +532,30 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
{
int extdatalen=0;
unsigned char *ret = p;
#ifndef OPENSSL_NO_EC
/* See if we support any ECC ciphersuites */
int using_ecc = 0;
if (s->version != DTLS1_VERSION && s->version >= TLS1_VERSION)
{
int i;
unsigned long alg_k, alg_a;
STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
{
SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)
|| (alg_a & SSL_aECDSA)))
{
using_ecc = 1;
break;
}
}
}
#endif
/* don't add extensions for SSLv3 unless doing secure renegotiation */
if (s->client_version == SSL3_VERSION
@ -460,51 +652,68 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
#endif
#ifndef OPENSSL_NO_EC
if (s->tlsext_ecpointformatlist != NULL &&
s->version != DTLS1_VERSION)
if (using_ecc)
{
/* Add TLS extension ECPointFormats to the ClientHello message */
long lenmax;
const unsigned char *plist;
size_t plistlen;
/* If we have a custom point format list use it otherwise
* use default */
plist = s->tlsext_ecpointformatlist;
if (plist)
plistlen = s->tlsext_ecpointformatlist_length;
else
{
plist = ecformats_default;
plistlen = sizeof(ecformats_default);
}
if ((lenmax = limit - ret - 5) < 0) return NULL;
if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
if (s->tlsext_ecpointformatlist_length > 255)
if (plistlen > (size_t)lenmax) return NULL;
if (plistlen > 255)
{
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
s2n(TLSEXT_TYPE_ec_point_formats,ret);
s2n(s->tlsext_ecpointformatlist_length + 1,ret);
*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
ret+=s->tlsext_ecpointformatlist_length;
}
if (s->tlsext_ellipticcurvelist != NULL &&
s->version != DTLS1_VERSION)
{
s2n(plistlen + 1,ret);
*(ret++) = (unsigned char)plistlen ;
memcpy(ret, plist, plistlen);
ret+=plistlen;
/* Add TLS extension EllipticCurves to the ClientHello message */
long lenmax;
plist = s->tlsext_ellipticcurvelist;
/* If we have a custom curve list use it otherwise
* use default */
if (plist)
plistlen = s->tlsext_ellipticcurvelist_length;
else
{
plist = eccurves_default;
plistlen = sizeof(eccurves_default);
}
if ((lenmax = limit - ret - 6) < 0) return NULL;
if (s->tlsext_ellipticcurvelist_length > (unsigned long)lenmax) return NULL;
if (s->tlsext_ellipticcurvelist_length > 65532)
if (plistlen > (size_t)lenmax) return NULL;
if (plistlen > 65532)
{
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
s2n(TLSEXT_TYPE_elliptic_curves,ret);
s2n(s->tlsext_ellipticcurvelist_length + 2, ret);
s2n(plistlen + 2, ret);
/* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for
* elliptic_curve_list, but the examples use two bytes.
* http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html
* resolves this to two bytes.
*/
s2n(s->tlsext_ellipticcurvelist_length, ret);
memcpy(ret, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
ret+=s->tlsext_ellipticcurvelist_length;
s2n(plistlen, ret);
memcpy(ret, plist, plistlen);
ret+=plistlen;
}
#endif /* OPENSSL_NO_EC */
@ -1641,59 +1850,6 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
int ssl_prepare_clienthello_tlsext(SSL *s)
{
#ifndef OPENSSL_NO_EC
/* If we are client and using an elliptic curve cryptography cipher suite, send the point formats
* and elliptic curves we support.
*/
int using_ecc = 0;
int i;
unsigned char *j;
unsigned long alg_k, alg_a;
STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
{
SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe) || (alg_a & SSL_aECDSA)))
{
using_ecc = 1;
break;
}
}
using_ecc = using_ecc && (s->version >= TLS1_VERSION);
if (using_ecc)
{
if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
{
SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
return -1;
}
s->tlsext_ecpointformatlist_length = 3;
s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
/* we support all named elliptic curves in draft-ietf-tls-ecc-12 */
if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist);
s->tlsext_ellipticcurvelist_length = sizeof(pref_list)/sizeof(pref_list[0]) * 2;
if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
{
s->tlsext_ellipticcurvelist_length = 0;
SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
return -1;
}
for (i = 0, j = s->tlsext_ellipticcurvelist; (unsigned int)i <
sizeof(pref_list)/sizeof(pref_list[0]); i++)
{
int id = tls1_ec_nid2curve_id(pref_list[i]);
s2n(id,j);
}
}
#endif /* OPENSSL_NO_EC */
#ifdef TLSEXT_TYPE_opaque_prf_input
{