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:
parent
751e26cb9b
commit
d0595f170c
10 changed files with 401 additions and 135 deletions
7
CHANGES
7
CHANGES
|
@ -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.
|
||||
|
|
23
apps/s_cb.c
23
apps/s_cb.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
26
ssl/s3_lib.c
26
ssl/s3_lib.c
|
@ -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 :-) */
|
||||
|
|
27
ssl/ssl.h
27
ssl/ssl.h
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
352
ssl/t1_lib.c
352
ssl/t1_lib.c
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue