Move ServerHello extension construction into the new extensions framework
This lays the foundation for a later move to have the extensions built and placed into the correct message for TLSv1.3 (e.g. ServerHello or EncryptedExtensions). Perl changes reviewed by Richard Levitte. Non-perl changes reviewed by Rich Salz Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
parent
25670f3e87
commit
7da160b0f4
9 changed files with 471 additions and 382 deletions
|
@ -2275,10 +2275,22 @@ int ERR_load_SSL_strings(void);
|
|||
# define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST 373
|
||||
# define SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET 428
|
||||
# define SSL_F_TLS_CONSTRUCT_NEXT_PROTO 426
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_ALPN 451
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE 374
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_CRYPTOPRO_BUG 452
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_DONE 375
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_EC_PT_FORMATS 453
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_EMS 454
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_ETM 455
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_HELLO 376
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE 377
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE 456
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_NEXT_PROTO_NEG 457
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_RENEGOTIATE 458
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_SERVER_NAME 459
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET 460
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST 461
|
||||
# define SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP 462
|
||||
# define SSL_F_TLS_GET_MESSAGE_BODY 351
|
||||
# define SSL_F_TLS_GET_MESSAGE_HEADER 387
|
||||
# define SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE 445
|
||||
|
|
|
@ -282,13 +282,34 @@ static ERR_STRING_DATA SSL_str_functs[] = {
|
|||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET),
|
||||
"tls_construct_new_session_ticket"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_NEXT_PROTO), "tls_construct_next_proto"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_ALPN), "tls_construct_server_alpn"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE),
|
||||
"tls_construct_server_certificate"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_CRYPTOPRO_BUG),
|
||||
"tls_construct_server_cryptopro_bug"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_DONE), "tls_construct_server_done"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_EC_PT_FORMATS),
|
||||
"tls_construct_server_ec_pt_formats"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_EMS), "tls_construct_server_ems"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_ETM), "tls_construct_server_etm"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_HELLO),
|
||||
"tls_construct_server_hello"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE),
|
||||
"tls_construct_server_key_exchange"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE),
|
||||
"tls_construct_server_key_share"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_NEXT_PROTO_NEG),
|
||||
"tls_construct_server_next_proto_neg"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_RENEGOTIATE),
|
||||
"tls_construct_server_renegotiate"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_SERVER_NAME),
|
||||
"tls_construct_server_server_name"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET),
|
||||
"tls_construct_server_session_ticket"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST),
|
||||
"tls_construct_server_status_request"},
|
||||
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP),
|
||||
"tls_construct_server_use_srtp"},
|
||||
{ERR_FUNC(SSL_F_TLS_GET_MESSAGE_BODY), "tls_get_message_body"},
|
||||
{ERR_FUNC(SSL_F_TLS_GET_MESSAGE_HEADER), "tls_get_message_header"},
|
||||
{ERR_FUNC(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE),
|
||||
|
|
|
@ -2064,6 +2064,8 @@ __owur int tls1_set_groups(unsigned char **pext, size_t *pextlen,
|
|||
int *curves, size_t ncurves);
|
||||
__owur int tls1_set_groups_list(unsigned char **pext, size_t *pextlen,
|
||||
const char *str);
|
||||
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
|
||||
size_t *num_formats);
|
||||
__owur int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
|
||||
__owur EVP_PKEY *ssl_generate_pkey_curve(int id);
|
||||
# endif /* OPENSSL_NO_EC */
|
||||
|
@ -2076,18 +2078,17 @@ __owur int tls1_get_curvelist(SSL *s, int sess, const unsigned char **pcurves,
|
|||
size_t *num_curves);
|
||||
|
||||
__owur int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al);
|
||||
__owur int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al);
|
||||
void ssl_set_default_md(SSL *s);
|
||||
__owur int tls1_set_server_sigalgs(SSL *s);
|
||||
__owur int ssl_check_clienthello_tlsext_late(SSL *s, int *al);
|
||||
__owur int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt);
|
||||
__owur int ssl_prepare_clienthello_tlsext(SSL *s);
|
||||
__owur int ssl_prepare_serverhello_tlsext(SSL *s);
|
||||
__owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts,
|
||||
size_t numexts,
|
||||
unsigned int type);
|
||||
__owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
|
||||
SSL_SESSION **ret);
|
||||
__owur int tls_use_ticket(SSL *s);
|
||||
|
||||
__owur int tls12_get_sigandhash(WPACKET *pkt, const EVP_PKEY *pk,
|
||||
const EVP_MD *md);
|
||||
|
@ -2116,7 +2117,6 @@ __owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex,
|
|||
|
||||
__owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
|
||||
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
|
||||
__owur int ssl_add_serverhello_renegotiate_ext(SSL *s, WPACKET *pkt);
|
||||
__owur int ssl_parse_serverhello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
|
||||
__owur long ssl_get_algorithm2(SSL *s);
|
||||
__owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
|
||||
|
|
|
@ -31,7 +31,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_renegotiate,
|
||||
tls_parse_clienthello_renegotiate,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_renegotiate,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED
|
||||
| EXT_TLS1_2_AND_BELOW_ONLY
|
||||
|
@ -40,7 +40,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_server_name,
|
||||
tls_parse_clienthello_server_name,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_server_name,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO
|
||||
|
@ -60,7 +60,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_ec_point_formats,
|
||||
tls_parse_clienthello_ec_pt_formats,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_ec_pt_formats,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
|
@ -68,7 +68,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_supported_groups,
|
||||
tls_parse_clienthello_supported_groups,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL /* TODO(TLS1.3): Need to add this */,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO
|
||||
| /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO
|
||||
|
@ -78,7 +78,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_session_ticket,
|
||||
tls_parse_clienthello_session_ticket,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_session_ticket,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
|
@ -94,7 +94,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_status_request,
|
||||
tls_parse_clienthello_status_request,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_status_request,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| /*EXT_TLS1_3_CERTIFICATE*/EXT_TLS1_3_SERVER_HELLO
|
||||
|
@ -104,7 +104,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_next_proto_neg,
|
||||
tls_parse_clienthello_npn,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_next_proto_neg,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
|
@ -113,25 +113,27 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_application_layer_protocol_negotiation,
|
||||
tls_parse_clienthello_alpn,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_alpn,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO
|
||||
},
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
{
|
||||
TLSEXT_TYPE_use_srtp,
|
||||
tls_parse_clienthello_use_srtp,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_use_srtp,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
|
||||
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY
|
||||
},
|
||||
#endif
|
||||
{
|
||||
TLSEXT_TYPE_encrypt_then_mac,
|
||||
tls_parse_clienthello_etm,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_etm,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
|
@ -153,7 +155,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_extended_master_secret,
|
||||
tls_parse_clienthello_ems,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_ems,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
},
|
||||
|
@ -179,11 +181,23 @@ static const EXTENSION_DEFINITION ext_defs[] = {
|
|||
TLSEXT_TYPE_key_share,
|
||||
tls_parse_clienthello_key_share,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_key_share,
|
||||
NULL,
|
||||
EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO
|
||||
| EXT_TLS1_3_HELLO_RETRY_REQUEST | EXT_TLS_IMPLEMENTATION_ONLY
|
||||
| EXT_TLS1_3_ONLY
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Special unsolicited ServerHello extension only used when
|
||||
* SSL_OP_CRYPTOPRO_TLSEXT_BUG is set
|
||||
*/
|
||||
TLSEXT_TYPE_cryptopro_bug,
|
||||
NULL,
|
||||
NULL,
|
||||
tls_construct_server_cryptopro_bug,
|
||||
NULL,
|
||||
EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -440,15 +454,21 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
|||
size_t loop;
|
||||
int addcustom = 0;
|
||||
|
||||
/*
|
||||
* Normally if something goes wrong during construction its an internal
|
||||
* error. We can always override this later.
|
||||
*/
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)
|
||||
/*
|
||||
* If extensions are of zero length then we don't even add the
|
||||
* extensions length bytes to a ClientHello
|
||||
* extensions length bytes to a ClientHello/ServerHello in SSLv3
|
||||
*/
|
||||
|| ((context & EXT_CLIENT_HELLO) != 0
|
||||
|| ((context & (EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO)) != 0
|
||||
&& s->version == SSL3_VERSION
|
||||
&& !WPACKET_set_flags(pkt,
|
||||
WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
@ -504,7 +524,6 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
|||
}
|
||||
|
||||
if (!WPACKET_close(pkt)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -647,3 +647,373 @@ int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the ALPN extension in a ClientHello.
|
||||
* al: a pointer to the alert value to send in the event of a failure.
|
||||
* returns 1 on success, 0 on error.
|
||||
*/
|
||||
static int tls1_alpn_handle_client_hello_late(SSL *s, int *al)
|
||||
{
|
||||
const unsigned char *selected = NULL;
|
||||
unsigned char selected_len = 0;
|
||||
|
||||
if (s->ctx->alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
|
||||
int r = s->ctx->alpn_select_cb(s, &selected, &selected_len,
|
||||
s->s3->alpn_proposed,
|
||||
(unsigned int)s->s3->alpn_proposed_len,
|
||||
s->ctx->alpn_select_cb_arg);
|
||||
|
||||
if (r == SSL_TLSEXT_ERR_OK) {
|
||||
OPENSSL_free(s->s3->alpn_selected);
|
||||
s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
|
||||
if (s->s3->alpn_selected == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
s->s3->alpn_selected_len = selected_len;
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/* ALPN takes precedence over NPN. */
|
||||
s->s3->next_proto_neg_seen = 0;
|
||||
#endif
|
||||
} else {
|
||||
*al = SSL_AD_NO_APPLICATION_PROTOCOL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon success, returns 1.
|
||||
* Upon failure, returns 0 and sets |al| to the appropriate fatal alert.
|
||||
*/
|
||||
int ssl_check_clienthello_tlsext_late(SSL *s, int *al)
|
||||
{
|
||||
s->tlsext_status_expected = 0;
|
||||
|
||||
/*
|
||||
* If status request then ask callback what to do. Note: this must be
|
||||
* called after servername callbacks in case the certificate has changed,
|
||||
* and must be called after the cipher has been chosen because this may
|
||||
* influence which certificate is sent
|
||||
*/
|
||||
if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) {
|
||||
int ret;
|
||||
CERT_PKEY *certpkey;
|
||||
certpkey = ssl_get_server_send_pkey(s);
|
||||
/* If no certificate can't return certificate status */
|
||||
if (certpkey != NULL) {
|
||||
/*
|
||||
* Set current certificate to one we will use so SSL_get_certificate
|
||||
* et al can pick it up.
|
||||
*/
|
||||
s->cert->key = certpkey;
|
||||
ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
|
||||
switch (ret) {
|
||||
/* We don't want to send a status request response */
|
||||
case SSL_TLSEXT_ERR_NOACK:
|
||||
s->tlsext_status_expected = 0;
|
||||
break;
|
||||
/* status request response should be sent */
|
||||
case SSL_TLSEXT_ERR_OK:
|
||||
if (s->tlsext_ocsp_resp)
|
||||
s->tlsext_status_expected = 1;
|
||||
break;
|
||||
/* something bad happened */
|
||||
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
||||
default:
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tls1_alpn_handle_client_hello_late(s, al)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add the server's renegotiation binding */
|
||||
int tls_construct_server_renegotiate(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (!s->s3->send_connection_binding)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
|| !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len)
|
||||
|| !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
|
||||
s->s3->previous_server_finished_len)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_RENEGOTIATE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_server_server_name(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (s->hit || s->servername_done != 1
|
||||
|| s->session->tlsext_hostname == NULL)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_SERVER_NAME, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_construct_server_ec_pt_formats(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
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_kECDHE) || (alg_a & SSL_aECDSA);
|
||||
using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
|
||||
const unsigned char *plist;
|
||||
size_t plistlen;
|
||||
|
||||
if (!using_ecc)
|
||||
return 1;
|
||||
|
||||
tls1_get_formatlist(s, &plist, &plistlen);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_server_session_ticket(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (!s->tlsext_ticket_expected || !tls_use_ticket(s)) {
|
||||
s->tlsext_ticket_expected = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (!s->tlsext_status_expected)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_construct_server_next_proto_neg(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
const unsigned char *npa;
|
||||
unsigned int npalen;
|
||||
int ret;
|
||||
int next_proto_neg_seen = s->s3->next_proto_neg_seen;
|
||||
|
||||
s->s3->next_proto_neg_seen = 0;
|
||||
if (!next_proto_neg_seen || s->ctx->next_protos_advertised_cb == NULL)
|
||||
return 1;
|
||||
|
||||
ret = s->ctx->next_protos_advertised_cb(s, &npa, &npalen,
|
||||
s->ctx->next_protos_advertised_cb_arg);
|
||||
if (ret == SSL_TLSEXT_ERR_OK) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_NEXT_PROTO_NEG,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->s3->next_proto_neg_seen = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_server_alpn(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (s->s3->alpn_selected == NULL)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt,
|
||||
TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
|
||||
s->s3->alpn_selected_len)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_ALPN, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_construct_server_use_srtp(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if (s->srtp_profile == NULL)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 2)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
|
||||
|| !WPACKET_put_bytes_u8(pkt, 0)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_server_etm(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if ((s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) == 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
|
||||
* for other cases too.
|
||||
*/
|
||||
if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
|
||||
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_ETM, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_server_ems(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_EMS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_server_key_share(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
unsigned char *encodedPoint;
|
||||
size_t encoded_pt_len = 0;
|
||||
EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
|
||||
|
||||
if (s->hit)
|
||||
return 1;
|
||||
|
||||
if (ckey == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skey = ssl_generate_pkey(ckey);
|
||||
if (skey == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generate encoding of server key */
|
||||
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
|
||||
if (encoded_pt_len == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_EC_LIB);
|
||||
EVP_PKEY_free(skey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(skey);
|
||||
OPENSSL_free(encodedPoint);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_free(encodedPoint);
|
||||
|
||||
/* This causes the crypto state to be updated based on the derived keys */
|
||||
s->s3->tmp.pkey = skey;
|
||||
if (ssl_derive(s, skey, ckey, 1) == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_server_cryptopro_bug(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
const unsigned char cryptopro_ext[36] = {
|
||||
0xfd, 0xe8, /* 65000 */
|
||||
0x00, 0x20, /* 32 bytes length */
|
||||
0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
|
||||
0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
|
||||
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
|
||||
};
|
||||
|
||||
if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
|
||||
&& (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
|
||||
|| (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
|
||||
return 1;
|
||||
|
||||
if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -179,3 +179,22 @@ int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al);
|
|||
int tls_parse_clienthello_etm(SSL *s, PACKET *pkt, int *al);
|
||||
int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al);
|
||||
int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al);
|
||||
|
||||
int tls_construct_server_renegotiate(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_server_name(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_ec_pt_formats(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_session_ticket(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_next_proto_neg(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_alpn(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_use_srtp(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_etm(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_ems(SSL *s, WPACKET *pkt, int *al);
|
||||
int tls_construct_server_key_share(SSL *s, WPACKET *pkt, int *al);
|
||||
|
||||
/*
|
||||
* Not in public headers as this is not an official extension. Only used when
|
||||
* SSL_OP_CRYPTOPRO_TLSEXT_BUG is set.
|
||||
*/
|
||||
#define TLSEXT_TYPE_cryptopro_bug 0xfde8
|
||||
int tls_construct_server_cryptopro_bug(SSL *s, WPACKET *pkt, int *al);
|
||||
|
|
|
@ -1980,15 +1980,20 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
|
|||
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
|
||||
|| (!SSL_IS_TLS13(s)
|
||||
&& !WPACKET_put_bytes_u8(pkt, compm))
|
||||
|| !ssl_prepare_serverhello_tlsext(s)
|
||||
|| !ssl_add_serverhello_tlsext(s, pkt, &al)) {
|
||||
/*
|
||||
* TODO(TLS1.3): For now we add all 1.2 and 1.3 extensions. Later
|
||||
* we will do this based on the actual protocol
|
||||
*/
|
||||
|| !tls_construct_extensions(s, pkt,
|
||||
EXT_TLS1_2_SERVER_HELLO
|
||||
| EXT_TLS1_3_SERVER_HELLO, &al)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
344
ssl/t1_lib.c
344
ssl/t1_lib.c
|
@ -596,7 +596,7 @@ static int tls1_check_ec_key(SSL *s,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
|
||||
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
|
||||
size_t *num_formats)
|
||||
{
|
||||
/*
|
||||
|
@ -939,7 +939,7 @@ int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op)
|
|||
return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
|
||||
}
|
||||
|
||||
static int tls_use_ticket(SSL *s)
|
||||
int tls_use_ticket(SSL *s)
|
||||
{
|
||||
if ((s->options & SSL_OP_NO_TICKET) || SSL_IS_TLS13(s))
|
||||
return 0;
|
||||
|
@ -1512,289 +1512,6 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the key_share extension.
|
||||
*
|
||||
* Returns 1 on success or 0 on failure.
|
||||
*/
|
||||
static int add_client_key_share_ext(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
unsigned char *encodedPoint;
|
||||
size_t encoded_pt_len = 0;
|
||||
EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
|
||||
|
||||
if (ckey == NULL) {
|
||||
SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
|
||||
SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skey = ssl_generate_pkey(ckey);
|
||||
if (skey == NULL) {
|
||||
SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generate encoding of server key */
|
||||
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
|
||||
if (encoded_pt_len == 0) {
|
||||
SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_EC_LIB);
|
||||
EVP_PKEY_free(skey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(skey);
|
||||
OPENSSL_free(encodedPoint);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_free(encodedPoint);
|
||||
|
||||
/* This causes the crypto state to be updated based on the derived keys */
|
||||
s->s3->tmp.pkey = skey;
|
||||
if (ssl_derive(s, skey, ckey, 1) == 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al)
|
||||
{
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int next_proto_neg_seen;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
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_kECDHE) || (alg_a & SSL_aECDSA);
|
||||
using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
|
||||
#endif
|
||||
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->s3->send_connection_binding &&
|
||||
!ssl_add_serverhello_renegotiate_ext(s, pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only add RI for SSLv3 */
|
||||
if (s->version == SSL3_VERSION)
|
||||
goto done;
|
||||
|
||||
if (!s->hit && s->servername_done == 1
|
||||
&& s->session->tlsext_hostname != NULL) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_EC
|
||||
if (using_ecc) {
|
||||
const unsigned char *plist;
|
||||
size_t plistlen;
|
||||
/*
|
||||
* Add TLS extension ECPointFormats to the ServerHello message
|
||||
*/
|
||||
tls1_get_formatlist(s, &plist, &plistlen);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Currently the server should not respond with a SupportedCurves
|
||||
* extension
|
||||
*/
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
|
||||
if (s->tlsext_ticket_expected && tls_use_ticket(s)) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* if we don't add the above TLSEXT, we can't add a session ticket
|
||||
* later
|
||||
*/
|
||||
s->tlsext_ticket_expected = 0;
|
||||
}
|
||||
|
||||
if (s->tlsext_status_expected) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
if (SSL_IS_DTLS(s) && s->srtp_profile) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 2)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
|
||||
|| !WPACKET_put_bytes_u8(pkt, 0)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (((s->s3->tmp.new_cipher->id & 0xFFFF) == 0x80
|
||||
|| (s->s3->tmp.new_cipher->id & 0xFFFF) == 0x81)
|
||||
&& (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG)) {
|
||||
const unsigned char cryptopro_ext[36] = {
|
||||
0xfd, 0xe8, /* 65000 */
|
||||
0x00, 0x20, /* 32 bytes length */
|
||||
0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
|
||||
0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
|
||||
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
|
||||
};
|
||||
if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
next_proto_neg_seen = s->s3->next_proto_neg_seen;
|
||||
s->s3->next_proto_neg_seen = 0;
|
||||
if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) {
|
||||
const unsigned char *npa;
|
||||
unsigned int npalen;
|
||||
int r;
|
||||
|
||||
r = s->ctx->next_protos_advertised_cb(s, &npa, &npalen,
|
||||
s->
|
||||
ctx->next_protos_advertised_cb_arg);
|
||||
if (r == SSL_TLSEXT_ERR_OK) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->s3->next_proto_neg_seen = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SSL_IS_TLS13(s) && !s->hit && !add_client_key_share_ext(s, pkt, al))
|
||||
return 0;
|
||||
|
||||
if (!custom_ext_add(s, 1, pkt, al)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) {
|
||||
/*
|
||||
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
|
||||
* for other cases too.
|
||||
*/
|
||||
if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12)
|
||||
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
|
||||
else {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->s3->alpn_selected != NULL) {
|
||||
if (!WPACKET_put_bytes_u16(pkt,
|
||||
TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
|
||||
s->s3->alpn_selected_len)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the ALPN extension in a ClientHello.
|
||||
* al: a pointer to the alert value to send in the event of a failure.
|
||||
* returns 1 on success, 0 on error.
|
||||
*/
|
||||
static int tls1_alpn_handle_client_hello_late(SSL *s, int *al)
|
||||
{
|
||||
const unsigned char *selected = NULL;
|
||||
unsigned char selected_len = 0;
|
||||
|
||||
if (s->ctx->alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
|
||||
int r = s->ctx->alpn_select_cb(s, &selected, &selected_len,
|
||||
s->s3->alpn_proposed,
|
||||
(unsigned int)s->s3->alpn_proposed_len,
|
||||
s->ctx->alpn_select_cb_arg);
|
||||
|
||||
if (r == SSL_TLSEXT_ERR_OK) {
|
||||
OPENSSL_free(s->s3->alpn_selected);
|
||||
s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
|
||||
if (s->s3->alpn_selected == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
s->s3->alpn_selected_len = selected_len;
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/* ALPN takes precedence over NPN. */
|
||||
s->s3->next_proto_neg_seen = 0;
|
||||
#endif
|
||||
} else {
|
||||
*al = SSL_AD_NO_APPLICATION_PROTOCOL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/*
|
||||
* ssl_next_proto_validate validates a Next Protocol Negotiation block. No
|
||||
|
@ -2161,11 +1878,6 @@ int ssl_prepare_clienthello_tlsext(SSL *s)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int ssl_prepare_serverhello_tlsext(SSL *s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialise digests to default values */
|
||||
void ssl_set_default_md(SSL *s)
|
||||
{
|
||||
|
@ -2228,58 +1940,6 @@ int tls1_set_server_sigalgs(SSL *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon success, returns 1.
|
||||
* Upon failure, returns 0 and sets |al| to the appropriate fatal alert.
|
||||
*/
|
||||
int ssl_check_clienthello_tlsext_late(SSL *s, int *al)
|
||||
{
|
||||
s->tlsext_status_expected = 0;
|
||||
|
||||
/*
|
||||
* If status request then ask callback what to do. Note: this must be
|
||||
* called after servername callbacks in case the certificate has changed,
|
||||
* and must be called after the cipher has been chosen because this may
|
||||
* influence which certificate is sent
|
||||
*/
|
||||
if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) {
|
||||
int ret;
|
||||
CERT_PKEY *certpkey;
|
||||
certpkey = ssl_get_server_send_pkey(s);
|
||||
/* If no certificate can't return certificate status */
|
||||
if (certpkey != NULL) {
|
||||
/*
|
||||
* Set current certificate to one we will use so SSL_get_certificate
|
||||
* et al can pick it up.
|
||||
*/
|
||||
s->cert->key = certpkey;
|
||||
ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
|
||||
switch (ret) {
|
||||
/* We don't want to send a status request response */
|
||||
case SSL_TLSEXT_ERR_NOACK:
|
||||
s->tlsext_status_expected = 0;
|
||||
break;
|
||||
/* status request response should be sent */
|
||||
case SSL_TLSEXT_ERR_OK:
|
||||
if (s->tlsext_ocsp_resp)
|
||||
s->tlsext_status_expected = 1;
|
||||
break;
|
||||
/* something bad happened */
|
||||
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
||||
default:
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tls1_alpn_handle_client_hello_late(s, al)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl_check_serverhello_tlsext(SSL *s)
|
||||
{
|
||||
int ret = SSL_TLSEXT_ERR_NOACK;
|
||||
|
|
|
@ -11,23 +11,6 @@
|
|||
#include <openssl/objects.h>
|
||||
#include "ssl_locl.h"
|
||||
|
||||
/* Add the server's renegotiation binding */
|
||||
int ssl_add_serverhello_renegotiate_ext(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
|| !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len)
|
||||
|| !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
|
||||
s->s3->previous_server_finished_len)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the server's renegotiation binding and abort if it's not right
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue