diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index a6899213..d3e3c41a 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -440,10 +440,6 @@ struct ssl_session_st * efficient and to implement a maximum cache size. */ struct ssl_session_st *prev,*next; char *tlsext_hostname; - size_t tlsext_ecpointformatlist_length; - unsigned char *tlsext_ecpointformatlist; /* peer's list */ - size_t tlsext_ellipticcurvelist_length; - uint16_t *tlsext_ellipticcurvelist; /* peer's list */ /* RFC4507 info */ uint8_t *tlsext_tick; /* Session ticket */ size_t tlsext_ticklen; /* Session ticket length */ diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h index 3aea7523..2a201aa8 100644 --- a/include/openssl/ssl3.h +++ b/include/openssl/ssl3.h @@ -473,6 +473,18 @@ typedef struct ssl3_state_st * negotiated and the server is expected to send a * CertificateStatus message. */ char certificate_status_expected; + + /* peer_ecpointformatlist contains the EC point + * formats advertised by the peer. */ + uint8_t *peer_ecpointformatlist; + size_t peer_ecpointformatlist_length; + + /* Server-only: peer_ellipticcurvelist contains the EC + * curve IDs advertised by the peer. This is only set + * on the server's end. The server does not advertise + * this extension to the client. */ + uint16_t *peer_ellipticcurvelist; + size_t peer_ellipticcurvelist_length; } tmp; /* Connection binding to prevent renegotiation attacks */ diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 03997c93..215b3f6d 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -1019,6 +1019,10 @@ void ssl3_free(SSL *s) sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free); if (s->s3->tmp.certificate_types != NULL) OPENSSL_free(s->s3->tmp.certificate_types); + if (s->s3->tmp.peer_ecpointformatlist) + OPENSSL_free(s->s3->tmp.peer_ecpointformatlist); + if (s->s3->tmp.peer_ellipticcurvelist) + OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist); if (s->s3->handshake_buffer) { BIO_free(s->s3->handshake_buffer); } @@ -1275,12 +1279,8 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) case SSL_CTRL_GET_CURVES: { - const uint16_t *clist; - size_t clistlen; - if (!s->session) - return 0; - clist = s->session->tlsext_ellipticcurvelist; - clistlen = s->session->tlsext_ellipticcurvelist_length; + const uint16_t *clist = s->s3->tmp.peer_ellipticcurvelist; + size_t clistlen = s->s3->tmp.peer_ellipticcurvelist_length; if (parg) { size_t i; @@ -1385,12 +1385,11 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) } case SSL_CTRL_GET_EC_POINT_FORMATS: { - SSL_SESSION *sess = s->session; - const unsigned char **pformat = parg; - if (!sess || !sess->tlsext_ecpointformatlist) + if (!s->s3->tmp.peer_ecpointformatlist) return 0; - *pformat = sess->tlsext_ecpointformatlist; - return (int)sess->tlsext_ecpointformatlist_length; + const uint8_t **pformat = parg; + *pformat = s->s3->tmp.peer_ecpointformatlist; + return (int)s->s3->tmp.peer_ecpointformatlist_length; } case SSL_CTRL_CHANNEL_ID: diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index c8de7783..45f0e7af 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -709,10 +709,6 @@ void SSL_SESSION_free(SSL_SESSION *ss) if (ss->peer != NULL) X509_free(ss->peer); if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname); if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick); - ss->tlsext_ecpointformatlist_length = 0; - if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist); - ss->tlsext_ellipticcurvelist_length = 0; - if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist); if (ss->tlsext_signed_cert_timestamp_list != NULL) OPENSSL_free(ss->tlsext_signed_cert_timestamp_list); if (ss->ocsp_response != NULL) diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 12c67b95..4b13cfec 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -441,8 +441,8 @@ static void tls1_get_curvelist(SSL *s, int get_peer_curves, { if (get_peer_curves) { - *out_curve_ids = s->session->tlsext_ellipticcurvelist; - *out_curve_ids_len = s->session->tlsext_ellipticcurvelist_length; + *out_curve_ids = s->s3->tmp.peer_ellipticcurvelist; + *out_curve_ids_len = s->s3->tmp.peer_ellipticcurvelist_length; return; } @@ -590,8 +590,8 @@ static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id, uint8_t *out_co * peer's point format preferences. */ static int tls1_check_point_format(SSL *s, uint8_t comp_id) { - uint8_t *p = s->session->tlsext_ecpointformatlist; - size_t plen = s->session->tlsext_ecpointformatlist_length; + uint8_t *p = s->s3->tmp.peer_ecpointformatlist; + size_t plen = s->s3->tmp.peer_ecpointformatlist_length; size_t i; /* If point formats extension present check it, otherwise everything @@ -1206,7 +1206,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; int using_ecc = (alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA); - using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL); + using_ecc = using_ecc && (s->s3->tmp.peer_ecpointformatlist != NULL); /* don't add extensions for SSLv3, unless doing secure renegotiation */ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) return orig; @@ -1436,7 +1436,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) OPENSSL_free(s->cert->peer_sigalgs); s->cert->peer_sigalgs = NULL; } - /* Clear any shared sigtnature algorithms */ + /* Clear any shared signature algorithms */ if (s->cert->shared_sigalgs) { OPENSSL_free(s->cert->shared_sigalgs); @@ -1448,6 +1448,19 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) s->cert->pkeys[i].digest = NULL; s->cert->pkeys[i].valid_flags = 0; } + /* Clear ECC extensions */ + if (s->s3->tmp.peer_ecpointformatlist != 0) + { + OPENSSL_free(s->s3->tmp.peer_ecpointformatlist); + s->s3->tmp.peer_ecpointformatlist = NULL; + s->s3->tmp.peer_ecpointformatlist_length = 0; + } + if (s->s3->tmp.peer_ellipticcurvelist != 0) + { + OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist); + s->s3->tmp.peer_ellipticcurvelist = NULL; + s->s3->tmp.peer_ellipticcurvelist_length = 0; + } /* There may be no extensions. */ if (CBS_len(cbs) == 0) @@ -1593,15 +1606,12 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) return 0; } - if (!s->hit) + if (!CBS_stow(&ec_point_format_list, + &s->s3->tmp.peer_ecpointformatlist, + &s->s3->tmp.peer_ecpointformatlist_length)) { - if (!CBS_stow(&ec_point_format_list, - &s->session->tlsext_ecpointformatlist, - &s->session->tlsext_ecpointformatlist_length)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; } } else if (type == TLSEXT_TYPE_elliptic_curves) @@ -1618,37 +1628,34 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) return 0; } - if (!s->hit) + if (s->s3->tmp.peer_ellipticcurvelist) { - if (s->session->tlsext_ellipticcurvelist) - { - OPENSSL_free(s->session->tlsext_ellipticcurvelist); - s->session->tlsext_ellipticcurvelist_length = 0; - } - s->session->tlsext_ellipticcurvelist = - (uint16_t*)OPENSSL_malloc(CBS_len(&elliptic_curve_list)); - if (s->session->tlsext_ellipticcurvelist == NULL) + OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist); + s->s3->tmp.peer_ellipticcurvelist_length = 0; + } + s->s3->tmp.peer_ellipticcurvelist = + (uint16_t*)OPENSSL_malloc(CBS_len(&elliptic_curve_list)); + if (s->s3->tmp.peer_ellipticcurvelist == NULL) { *out_alert = SSL_AD_INTERNAL_ERROR; return 0; } - num_curves = CBS_len(&elliptic_curve_list) / 2; - for (i = 0; i < num_curves; i++) - { - if (!CBS_get_u16(&elliptic_curve_list, - &s->session->tlsext_ellipticcurvelist[i])) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - } - if (CBS_len(&elliptic_curve_list) != 0) + num_curves = CBS_len(&elliptic_curve_list) / 2; + for (i = 0; i < num_curves; i++) + { + if (!CBS_get_u16(&elliptic_curve_list, + &s->s3->tmp.peer_ellipticcurvelist[i])) { *out_alert = SSL_AD_INTERNAL_ERROR; return 0; } - s->session->tlsext_ellipticcurvelist_length = num_curves; } + if (CBS_len(&elliptic_curve_list) != 0) + { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + s->s3->tmp.peer_ellipticcurvelist_length = num_curves; } else if (type == TLSEXT_TYPE_session_ticket) { @@ -1851,6 +1858,14 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert) s->s3->alpn_selected = NULL; } + /* Clear ECC extensions */ + if (s->s3->tmp.peer_ecpointformatlist != 0) + { + OPENSSL_free(s->s3->tmp.peer_ecpointformatlist); + s->s3->tmp.peer_ecpointformatlist = NULL; + s->s3->tmp.peer_ecpointformatlist_length = 0; + } + /* There may be no extensions. */ if (CBS_len(cbs) == 0) { @@ -1911,15 +1926,12 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert) return 0; } - if (!s->hit) + if (!CBS_stow(&ec_point_format_list, + &s->s3->tmp.peer_ecpointformatlist, + &s->s3->tmp.peer_ecpointformatlist_length)) { - if (!CBS_stow(&ec_point_format_list, - &s->session->tlsext_ecpointformatlist, - &s->session->tlsext_ecpointformatlist_length)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; } } else if (type == TLSEXT_TYPE_session_ticket)