ret+=2;
if (ret>=limit) return NULL; /* this really never occurs, but ... */
- if (s->servername_done == 0 && s->tlsext_hostname != NULL)
+ if (s->tlsext_hostname != NULL)
{
/* Add TLS extension servername to the Client Hello message */
unsigned long size_str;
long lenmax;
- if ((lenmax = limit - p - 7) < 0) return NULL;
- if ((size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) return NULL;
+ /* check for enough space.
+ 4 for the servername type and entension length
+ 2 for servernamelist length
+ 1 for the hostname type
+ 2 for hostname length
+ + hostname length
+ */
+
+ if ((lenmax = limit - p - 9) < 0
+ || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax)
+ return NULL;
+
+ /* extension type and length */
+ s2n(TLSEXT_TYPE_server_name,ret);
+ s2n(size_str+5,ret);
- s2n(TLSEXT_TYPE_server_name,ret);
+ /* length of servername list */
s2n(size_str+3,ret);
+
+ /* hostname type, length and hostname */
*(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name;
s2n(size_str,ret);
-
memcpy(ret, s->tlsext_hostname, size_str);
ret+=size_str;
+
}
#ifndef OPENSSL_NO_EC
if (s->tlsext_ecpointformatlist != NULL)
memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
ret+=s->tlsext_ecpointformatlist_length;
}
+ if (s->tlsext_ellipticcurvelist != NULL)
+ {
+ /* Add TLS extension EllipticCurves to the ClientHello message */
+ long lenmax;
+
+ if ((lenmax = limit - p - 5) < 0) return NULL;
+ if (s->tlsext_ellipticcurvelist_length > (unsigned long)lenmax) return NULL;
+ if (s->tlsext_ellipticcurvelist_length > 255)
+ {
+ 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(s->tlsext_ellipticcurvelist_length, ret);
+ memcpy(ret, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
+ ret+=s->tlsext_ellipticcurvelist_length;
+ }
#endif /* OPENSSL_NO_EC */
if ((extdatalen = ret-p-2)== 0)
*(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
ret+=s->tlsext_ecpointformatlist_length;
+
}
+ /* Currently the server should not respond with a SupportedCurves extension */
#endif /* OPENSSL_NO_EC */
if ((extdatalen = ret-p-2)== 0)
unsigned short size;
unsigned short len;
unsigned char *data = *p;
-#if 0
- fprintf(stderr,"ssl_parse_clienthello_tlsext %s\n",s->session->tlsext_hostname?s->session->tlsext_hostname:"NULL");
-#endif
s->servername_done = 0;
if (data >= (d+n-2))
if (type == TLSEXT_TYPE_server_name)
{
- unsigned char *sdata = data;
+ unsigned char *sdata;
int servname_type;
- int dsize = size-3 ;
-
- if (dsize > 0 )
+ int dsize;
+
+ if (size < 2)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ n2s(data,dsize);
+ size -= 2;
+ if (dsize > size )
{
- servname_type = *(sdata++);
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ sdata = data;
+ while (dsize > 3)
+ {
+ servname_type = *(sdata++);
n2s(sdata,len);
- if (len != dsize)
+ dsize -= 3;
+
+ if (len > dsize)
{
*al = SSL_AD_DECODE_ERROR;
return 0;
}
-
+ if (s->servername_done == 0)
switch (servname_type)
{
case TLSEXT_NAMETYPE_host_name:
}
s->servername_done = 1;
-#if 0
- fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_hostname %s\n",s->session->tlsext_hostname);
-#endif
}
else
s->servername_done = strlen(s->session->tlsext_hostname) == len
break;
}
+ dsize -= len;
+ }
+ if (dsize != 0)
+ {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
}
+
}
#ifndef OPENSSL_NO_EC
fprintf(stderr,"\n");
#endif
}
+ else if (type == TLSEXT_TYPE_elliptic_curves)
+ {
+ unsigned char *sdata = data;
+ int ellipticcurvelist_length = (*(sdata++) << 8);
+ ellipticcurvelist_length += (*(sdata++));
+
+ if (ellipticcurvelist_length != size - 2)
+ {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ s->session->tlsext_ellipticcurvelist_length = 0;
+ if (s->session->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->session->tlsext_ellipticcurvelist);
+ if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL)
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->session->tlsext_ellipticcurvelist_length = ellipticcurvelist_length;
+ memcpy(s->session->tlsext_ellipticcurvelist, sdata, ellipticcurvelist_length);
+#if 0
+ fprintf(stderr,"ssl_parse_clienthello_tlsext s->session->tlsext_ellipticcurvelist (length=%i) ", s->session->tlsext_ellipticcurvelist_length);
+ sdata = s->session->tlsext_ellipticcurvelist;
+ for (i = 0; i < s->session->tlsext_ellipticcurvelist_length; i++)
+ fprintf(stderr,"%i ",*(sdata++));
+ fprintf(stderr,"\n");
+#endif
+ }
+#endif /* OPENSSL_NO_EC */
data+=size;
}
-#endif /* OPENSSL_NO_EC */
*p = data;
return 1;
unsigned char *data = *p;
int tlsext_servername = 0;
-#ifndef OPENSSL_NO_EC
- int tlsext_ecpointformats = 0;
-#endif /* OPENSSL_NO_EC */
if (data >= (d+n-2))
return 1;
fprintf(stderr,"\n");
#endif
}
-
+#endif /* OPENSSL_NO_EC */
data+=size;
}
-#endif /* OPENSSL_NO_EC */
if (data != d+n)
{
}
}
+ *p = data;
+ return 1;
+}
+
#ifndef OPENSSL_NO_EC
- if (!s->hit && tlsext_ecpointformats == 1)
+static int nid_list[] =
+ {
+ NID_sect163k1, /* sect163k1 (1) */
+ NID_sect163r1, /* sect163r1 (2) */
+ NID_sect163r2, /* sect163r2 (3) */
+ NID_sect193r1, /* sect193r1 (4) */
+ NID_sect193r2, /* sect193r2 (5) */
+ NID_sect233k1, /* sect233k1 (6) */
+ NID_sect233r1, /* sect233r1 (7) */
+ NID_sect239k1, /* sect239k1 (8) */
+ NID_sect283k1, /* sect283k1 (9) */
+ NID_sect283r1, /* sect283r1 (10) */
+ NID_sect409k1, /* sect409k1 (11) */
+ NID_sect409r1, /* sect409r1 (12) */
+ NID_sect571k1, /* sect571k1 (13) */
+ NID_sect571r1, /* sect571r1 (14) */
+ NID_secp160k1, /* secp160k1 (15) */
+ NID_secp160r1, /* secp160r1 (16) */
+ NID_secp160r2, /* secp160r2 (17) */
+ NID_secp192k1, /* secp192k1 (18) */
+ NID_X9_62_prime192v1, /* secp192r1 (19) */
+ NID_secp224k1, /* secp224k1 (20) */
+ NID_secp224r1, /* secp224r1 (21) */
+ NID_secp256k1, /* secp256k1 (22) */
+ NID_X9_62_prime256v1, /* secp256r1 (23) */
+ NID_secp384r1, /* secp384r1 (24) */
+ NID_secp521r1 /* secp521r1 (25) */
+ };
+
+int tls1_ec_curve_id2nid(int curve_id)
+ {
+ /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+ if ((curve_id < 1) || (curve_id > sizeof(nid_list)/sizeof(nid_list[0]))) return 0;
+ return nid_list[curve_id-1];
+ }
+
+int tls1_ec_nid2curve_id(int nid)
+ {
+ /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+ switch (nid)
{
- if (s->tlsext_ecpointformatlist)
- {
- if (s->session->tlsext_ecpointformatlist == NULL)
- {
- s->session->tlsext_ecpointformatlist_length = s->tlsext_ecpointformatlist_length;
- if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
- if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == NULL)
- {
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
- }
- memcpy(s->session->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
- }
- else
- {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- }
+ case NID_sect163k1: /* sect163k1 (1) */
+ return 1;
+ case NID_sect163r1: /* sect163r1 (2) */
+ return 2;
+ case NID_sect163r2: /* sect163r2 (3) */
+ return 3;
+ case NID_sect193r1: /* sect193r1 (4) */
+ return 4;
+ case NID_sect193r2: /* sect193r2 (5) */
+ return 5;
+ case NID_sect233k1: /* sect233k1 (6) */
+ return 6;
+ case NID_sect233r1: /* sect233r1 (7) */
+ return 7;
+ case NID_sect239k1: /* sect239k1 (8) */
+ return 8;
+ case NID_sect283k1: /* sect283k1 (9) */
+ return 9;
+ case NID_sect283r1: /* sect283r1 (10) */
+ return 10;
+ case NID_sect409k1: /* sect409k1 (11) */
+ return 11;
+ case NID_sect409r1: /* sect409r1 (12) */
+ return 12;
+ case NID_sect571k1: /* sect571k1 (13) */
+ return 13;
+ case NID_sect571r1: /* sect571r1 (14) */
+ return 14;
+ case NID_secp160k1: /* secp160k1 (15) */
+ return 15;
+ case NID_secp160r1: /* secp160r1 (16) */
+ return 16;
+ case NID_secp160r2: /* secp160r2 (17) */
+ return 17;
+ case NID_secp192k1: /* secp192k1 (18) */
+ return 18;
+ case NID_X9_62_prime192v1: /* secp192r1 (19) */
+ return 19;
+ case NID_secp224k1: /* secp224k1 (20) */
+ return 20;
+ case NID_secp224r1: /* secp224r1 (21) */
+ return 21;
+ case NID_secp256k1: /* secp256k1 (22) */
+ return 22;
+ case NID_X9_62_prime256v1: /* secp256r1 (23) */
+ return 23;
+ case NID_secp384r1: /* secp384r1 (24) */
+ return 24;
+ case NID_secp521r1: /* secp521r1 (25) */
+ return 25;
+ default:
+ return 0;
}
+ }
#endif /* OPENSSL_NO_EC */
- *p = data;
- return 1;
-}
-
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 we
- * support.
+ /* 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;
int algs;
STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
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(nid_list)/sizeof(nid_list[0]) * 2;
+ if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
+ {
+ s->tlsext_ellipticcurvelist_length = 0;
+ SSLerr(SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ for (i = 1, j = s->tlsext_ellipticcurvelist; i <= sizeof(nid_list)/sizeof(nid_list[0]); i++)
+ s2n(i,j);
}
#endif /* OPENSSL_NO_EC */
return 1;
{
#ifndef OPENSSL_NO_EC
/* If we are server and using an ECC cipher suite, send the point formats we support
- * if the client sent us an ECPointsFormat extension.
+ * if the client sent us an ECPointsFormat extension. Note that the server is not
+ * supposed to send an EllipticCurves extension.
*/
int algs = s->s3->tmp.new_cipher->algorithms;
int using_ecc = (algs & SSL_kECDH) || (algs & SSL_kECDHE) || (algs & SSL_aECDSA);
int al = SSL_AD_UNRECOGNIZED_NAME;
#ifndef OPENSSL_NO_EC
- /* If we are server and using an elliptic curve cyrptography cipher suite, then we don't
- * need to check EC point formats since all clients must support uncompressed and it's the
- * only thing we support; we just need to copy the data in. We probably ought to check it
- * for validity, but we never use it.
+ /* The handling of the ECPointFormats extension is done elsewhere, namely in
+ * ssl3_choose_cipher in s3_lib.c.
+ */
+ /* The handling of the EllipticCurves extension is done elsewhere, namely in
+ * ssl3_choose_cipher in s3_lib.c.
*/
#endif
((algs & SSL_kECDH) || (algs & SSL_kECDHE) || (algs & SSL_aECDSA)))
{
/* we are using an ECC cipher */
- int i;
+ size_t i;
unsigned char *list;
int found_uncompressed = 0;
- if ((s->session->tlsext_ecpointformatlist == NULL) || (s->session->tlsext_ecpointformatlist_length <= 0))
+ if ((s->session->tlsext_ecpointformatlist == NULL) || (s->session->tlsext_ecpointformatlist_length == 0))
{
SSLerr(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT,SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
return -1;
}
}
#endif
+