Refactor ClientHello extension parsing

This builds on the work started in 1ab3836b3 and extends is so that
each extension has its own identified parsing functions, as well as an
allowed context identifying which messages and protocols it is relevant for.
Subsequent commits will do a similar job for the ServerHello extensions.
This will enable us to have common functions for processing extension blocks
no matter which of the multiple messages they are received from. In TLSv1.3
a number of different messages have extension blocks, and some extensions
have moved from one message to another when compared to TLSv1.2.

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:
Matt Caswell 2016-11-24 16:59:48 +00:00
parent fadd9a1e2d
commit 6b473acabd
12 changed files with 1284 additions and 1164 deletions

View File

@ -2280,6 +2280,8 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE 377
# 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
# define SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP 446
# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 378
# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE 384
# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE 360

View File

@ -2,7 +2,7 @@ LIBS=../libssl
SOURCE[../libssl]=\
pqueue.c packet.c \
statem/statem_srvr.c statem/statem_clnt.c s3_lib.c s3_enc.c record/rec_layer_s3.c \
statem/statem_lib.c statem/statem_extensions.c s3_cbc.c s3_msg.c \
statem/statem_lib.c statem/extensions.c s3_cbc.c s3_msg.c \
methods.c t1_lib.c t1_enc.c tls13_enc.c t1_ext.c \
d1_lib.c record/rec_layer_d1.c d1_msg.c \
statem/statem_dtls.c d1_srtp.c \

View File

@ -137,73 +137,6 @@ SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s)
return s->srtp_profile;
}
int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
{
SRTP_PROTECTION_PROFILE *sprof;
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
unsigned int ct, mki_len, id;
int i, srtp_pref;
PACKET subpkt;
/* Pull off the length of the cipher suite list and check it is even */
if (!PACKET_get_net_2(pkt, &ct)
|| (ct & 1) != 0 || !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
*al = SSL_AD_DECODE_ERROR;
return 1;
}
srvr = SSL_get_srtp_profiles(s);
s->srtp_profile = NULL;
/* Search all profiles for a match initially */
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
while (PACKET_remaining(&subpkt)) {
if (!PACKET_get_net_2(&subpkt, &id)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
*al = SSL_AD_DECODE_ERROR;
return 1;
}
/*
* Only look for match in profiles of higher preference than
* current match.
* If no profiles have been have been configured then this
* does nothing.
*/
for (i = 0; i < srtp_pref; i++) {
sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
if (sprof->id == id) {
s->srtp_profile = sprof;
srtp_pref = i;
break;
}
}
}
/*
* Now extract the MKI value as a sanity check, but discard it for now
*/
if (!PACKET_get_1(pkt, &mki_len)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
*al = SSL_AD_DECODE_ERROR;
return 1;
}
if (!PACKET_forward(pkt, mki_len)
|| PACKET_remaining(pkt)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
SSL_R_BAD_SRTP_MKI_VALUE);
*al = SSL_AD_DECODE_ERROR;
return 1;
}
return 0;
}
int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
{
unsigned int id, ct, mki;

View File

@ -290,6 +290,10 @@ static ERR_STRING_DATA SSL_str_functs[] = {
"tls_construct_server_key_exchange"},
{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),
"tls_parse_clienthello_key_share"},
{ERR_FUNC(SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP),
"tls_parse_clienthello_use_srtp"},
{ERR_FUNC(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO),
"tls_post_process_client_hello"},
{ERR_FUNC(SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE),

View File

@ -1636,8 +1636,12 @@ typedef struct ssl3_comp_st {
# endif
typedef struct raw_extension_st {
/* The type of the extension */
unsigned int type;
/* Raw packet data for the extension */
PACKET data;
/* Set to 1 if we have already parsed the extension or 0 otherwise */
int parsed;
} RAW_EXTENSION;
#define MAX_COMPRESSIONS_SIZE 255
@ -2067,9 +2071,12 @@ __owur EVP_PKEY *ssl_generate_pkey_curve(int id);
__owur int tls1_shared_list(SSL *s,
const unsigned char *l1, size_t l1len,
const unsigned char *l2, size_t l2len, int nmatch);
__owur int tls_curve_allowed(SSL *s, const unsigned char *curve, int op);
__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);
__owur int ssl_parse_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello);
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);
@ -2081,7 +2088,6 @@ __owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts,
unsigned int type);
__owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
SSL_SESSION **ret);
__owur int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello);
__owur int tls12_get_sigandhash(WPACKET *pkt, const EVP_PKEY *pk,
const EVP_MD *md);
@ -2112,7 +2118,6 @@ __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 int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
__owur long ssl_get_algorithm2(SSL *s);
__owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
const unsigned char *psig, size_t psiglen);
@ -2124,7 +2129,6 @@ __owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
void ssl_set_client_disabled(SSL *s);
__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op);
__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
__owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
__owur int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,

1048
ssl/statem/extensions.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,252 +0,0 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
typedef struct {
/* The ID for the extension */
unsigned int type;
int (*server_parse)(SSL *s, PACKET *pkt);
int (*client_parse)(SSL *s, PACKET *pkt);
unsigned int context;
} EXTENSION_DEFINITION;
static const EXTENSION_DEFINITION ext_defs[] = {
{
TLSEXT_TYPE_renegotiate,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
},
{
TLSEXT_TYPE_server_name,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
},
{
TLSEXT_TYPE_srp,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
},
{
TLSEXT_TYPE_ec_point_formats,
NULL, NULL,
EXT_CLIENT_HELLO
},
{
TLSEXT_TYPE_supported_groups,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
},
{
TLSEXT_TYPE_session_ticket,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
},
{
TLSEXT_TYPE_signature_algorithms,
NULL, NULL,
EXT_CLIENT_HELLO
},
{
TLSEXT_TYPE_status_request,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_3_CERTIFICATE
},
{
TLSEXT_TYPE_next_proto_neg,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
},
{
TLSEXT_TYPE_application_layer_protocol_negotiation,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
},
{
TLSEXT_TYPE_use_srtp,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY
},
{
TLSEXT_TYPE_encrypt_then_mac,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
},
{
TLSEXT_TYPE_signed_certificate_timestamp,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_3_CERTIFICATE
},
{
TLSEXT_TYPE_extended_master_secret,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
},
{
TLSEXT_TYPE_supported_versions,
NULL, NULL,
EXT_CLIENT_HELLO
},
{
TLSEXT_TYPE_padding,
NULL, NULL,
EXT_CLIENT_HELLO
},
{
TLSEXT_TYPE_key_share,
NULL, NULL,
EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO
| EXT_TLS1_3_HELLO_RETRY_REQUEST
}
};
/*
* Comparison function used in a call to qsort (see tls_collect_extensions()
* below.)
* The two arguments |p1| and |p2| are expected to be pointers to RAW_EXTENSIONs
*
* Returns:
* 1 if the type for p1 is greater than p2
* 0 if the type for p1 and p2 are the same
* -1 if the type for p1 is less than p2
*/
static int compare_extensions(const void *p1, const void *p2)
{
const RAW_EXTENSION *e1 = (const RAW_EXTENSION *)p1;
const RAW_EXTENSION *e2 = (const RAW_EXTENSION *)p2;
if (e1->type < e2->type)
return -1;
else if (e1->type > e2->type)
return 1;
return 0;
}
/*
* Verify whether we are allowed to use the extension |type| in the current
* |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to
* indicate the extension is not allowed.
*/
static int verify_extension(SSL *s, unsigned int context, unsigned int type)
{
size_t i;
for (i = 0; i < OSSL_NELEM(ext_defs); i++) {
if (type == ext_defs[i].type) {
/* Check we're allowed to use this extension in this context */
if ((context & ext_defs[i].context) == 0)
return 0;
/* Make sure we don't use DTLS extensions in TLS */
if ((ext_defs[i].context & EXT_DTLS_ONLY) && !SSL_IS_DTLS(s))
return 0;
return 1;
}
}
/* Unknown extension. We allow it */
return 1;
}
/*
* Gather a list of all the extensions from the data in |packet]. |context|
* tells us which message this extension is for. The raw extension data is
* stored in |*res| with the number of found extensions in |*numfound|. In the
* event of an error the alert type to use is stored in |*ad|. We don't actually
* process the content of the extensions yet, except to check their types.
*
* Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
* more than one extension of the same type in a ClientHello or ServerHello.
* This function returns 1 if all extensions are unique and we have parsed their
* types, and 0 if the extensions contain duplicates, could not be successfully
* parsed, or an internal error occurred.
*/
/*
* TODO(TLS1.3): Refactor ServerHello extension parsing to use this and then
* remove tls1_check_duplicate_extensions()
*/
int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
RAW_EXTENSION **res, size_t *numfound, int *ad)
{
PACKET extensions = *packet;
size_t num_extensions = 0, i = 0;
RAW_EXTENSION *raw_extensions = NULL;
/* First pass: count the extensions. */
while (PACKET_remaining(&extensions) > 0) {
unsigned int type;
PACKET extension;
if (!PACKET_get_net_2(&extensions, &type) ||
!PACKET_get_length_prefixed_2(&extensions, &extension)) {
SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_BAD_EXTENSION);
*ad = SSL_AD_DECODE_ERROR;
goto err;
}
/* Verify this extension is allowed */
if (!verify_extension(s, context, type)) {
SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_BAD_EXTENSION);
*ad = SSL_AD_ILLEGAL_PARAMETER;
goto err;
}
num_extensions++;
}
if (num_extensions > 0) {
raw_extensions = OPENSSL_malloc(sizeof(*raw_extensions)
* num_extensions);
if (raw_extensions == NULL) {
*ad = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Second pass: collect the extensions. */
for (i = 0; i < num_extensions; i++) {
if (!PACKET_get_net_2(packet, &raw_extensions[i].type) ||
!PACKET_get_length_prefixed_2(packet,
&raw_extensions[i].data)) {
/* This should not happen. */
*ad = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (PACKET_remaining(packet) != 0) {
*ad = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_LENGTH_MISMATCH);
goto err;
}
/* Sort the extensions and make sure there are no duplicates. */
qsort(raw_extensions, num_extensions, sizeof(*raw_extensions),
compare_extensions);
for (i = 1; i < num_extensions; i++) {
if (raw_extensions[i - 1].type == raw_extensions[i].type) {
*ad = SSL_AD_DECODE_ERROR;
goto err;
}
}
}
*res = raw_extensions;
*numfound = num_extensions;
return 1;
err:
OPENSSL_free(raw_extensions);
return 0;
}

View File

@ -958,6 +958,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello)
const SSL_METHOD *best_method = NULL;
PACKET versionslist;
suppversions->parsed = 1;
if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) {
/* Trailing or invalid data? */
return SSL_R_LENGTH_MISMATCH;

View File

@ -27,15 +27,22 @@
#define FINISHED_MAX_LENGTH 64
/* Extension context codes */
#define EXT_DTLS_ONLY 0x01
#define EXT_CLIENT_HELLO 0x02
#define EXT_TLS_ONLY 0x0001
#define EXT_DTLS_ONLY 0x0002
/* Some extensions may be allowed in DTLS but we don't implement them for it */
#define EXT_TLS_IMPLEMENTATION_ONLY 0x0004
/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
#define EXT_SSL3_ALLOWED 0x0008
#define EXT_TLS1_2_AND_BELOW_ONLY 0x0010
#define EXT_TLS1_3_ONLY 0x0020
#define EXT_CLIENT_HELLO 0x0040
/* Really means TLS1.2 or below */
#define EXT_TLS1_2_SERVER_HELLO 0x04
#define EXT_TLS1_3_SERVER_HELLO 0x08
#define EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x10
#define EXT_TLS1_3_HELLO_RETRY_REQUEST 0x20
#define EXT_TLS1_3_CERTIFICATE 0x40
#define EXT_TLS1_3_NEW_SESSION_TICKET 0x80
#define EXT_TLS1_2_SERVER_HELLO 0x0080
#define EXT_TLS1_3_SERVER_HELLO 0x0100
#define EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0200
#define EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0400
#define EXT_TLS1_3_CERTIFICATE 0x0800
#define EXT_TLS1_3_NEW_SESSION_TICKET 0x1000
/* Message processing return codes */
typedef enum {
@ -141,3 +148,8 @@ __owur MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
#endif
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
__owur int tls_parse_all_extensions(SSL *s, RAW_EXTENSION *exts, size_t numexts,
int *al);
__owur int tls_parse_extension(SSL *s, int type, RAW_EXTENSION *exts,
size_t numexts, int *al);

View File

@ -1062,6 +1062,196 @@ int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
return 1;
}
#ifndef OPENSSL_NO_EC
/*-
* ssl_check_for_safari attempts to fingerprint Safari using OS X
* SecureTransport using the TLS extension block in |hello|.
* Safari, since 10.6, sends exactly these extensions, in this order:
* SNI,
* elliptic_curves
* ec_point_formats
*
* We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
* but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
* Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
* 10.8..10.8.3 (which don't work).
*/
static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
{
unsigned int type;
PACKET sni, tmppkt;
size_t ext_len;
static const unsigned char kSafariExtensionsBlock[] = {
0x00, 0x0a, /* elliptic_curves extension */
0x00, 0x08, /* 8 bytes */
0x00, 0x06, /* 6 bytes of curve ids */
0x00, 0x17, /* P-256 */
0x00, 0x18, /* P-384 */
0x00, 0x19, /* P-521 */
0x00, 0x0b, /* ec_point_formats */
0x00, 0x02, /* 2 bytes */
0x01, /* 1 point format */
0x00, /* uncompressed */
/* The following is only present in TLS 1.2 */
0x00, 0x0d, /* signature_algorithms */
0x00, 0x0c, /* 12 bytes */
0x00, 0x0a, /* 10 bytes */
0x05, 0x01, /* SHA-384/RSA */
0x04, 0x01, /* SHA-256/RSA */
0x02, 0x01, /* SHA-1/RSA */
0x04, 0x03, /* SHA-256/ECDSA */
0x02, 0x03, /* SHA-1/ECDSA */
};
/* Length of the common prefix (first two extensions). */
static const size_t kSafariCommonExtensionsLength = 18;
tmppkt = hello->extensions;
if (!PACKET_forward(&tmppkt, 2)
|| !PACKET_get_net_2(&tmppkt, &type)
|| !PACKET_get_length_prefixed_2(&tmppkt, &sni)) {
return;
}
if (type != TLSEXT_TYPE_server_name)
return;
ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ?
sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength;
s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
ext_len);
}
#endif /* !OPENSSL_NO_EC */
/*
* Process all remaining ClientHello extensions that we collected earlier and
* haven't already processed.
*
* Behaviour upon resumption is extension-specific. If the extension has no
* effect during resumption, it is parsed (to verify its format) but otherwise
* ignored. Returns 1 on success and 0 on failure. Upon failure, sets |al| to
* the appropriate alert.
*/
static int tls_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al)
{
/* Reset various flags that might get set by extensions during parsing */
s->servername_done = 0;
s->tlsext_status_type = -1;
#ifndef OPENSSL_NO_NEXTPROTONEG
s->s3->next_proto_neg_seen = 0;
#endif
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = NULL;
s->s3->alpn_selected_len = 0;
OPENSSL_free(s->s3->alpn_proposed);
s->s3->alpn_proposed = NULL;
s->s3->alpn_proposed_len = 0;
#ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
ssl_check_for_safari(s, hello);
#endif /* !OPENSSL_NO_EC */
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_sigalgs);
s->s3->tmp.peer_sigalgs = NULL;
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
#ifndef OPENSSL_NO_SRP
OPENSSL_free(s->srp_ctx.login);
s->srp_ctx.login = NULL;
#endif
s->srtp_profile = NULL;
/*
* We process the supported_groups extension first so that is done before
* we get to key_share which needs to use the information in it.
*/
if (!tls_parse_extension(s, TLSEXT_TYPE_supported_groups,
hello->pre_proc_exts, hello->num_extensions, al)) {
return 0;
}
/* Need RI if renegotiating */
if (s->renegotiate
&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
&& tls_get_extension_by_type(hello->pre_proc_exts,
hello->num_extensions,
TLSEXT_TYPE_renegotiate) == NULL) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT,
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
return tls_parse_all_extensions(s, hello->pre_proc_exts,
hello->num_extensions, al);
}
/*
* Check the results of extension parsing. Currently just calls the servername
* callback. Returns 1 for success or 0 for failure.
*/
static int tls_check_clienthello_tlsext(SSL *s)
{
int ret = SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
ret = s->ctx->tlsext_servername_callback(s, &al,
s->ctx->tlsext_servername_arg);
else if (s->initial_ctx != NULL
&& s->initial_ctx->tlsext_servername_callback != 0)
ret = s->initial_ctx->tlsext_servername_callback(s, &al,
s->initial_ctx->tlsext_servername_arg);
switch (ret) {
case SSL_TLSEXT_ERR_ALERT_FATAL:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
case SSL_TLSEXT_ERR_ALERT_WARNING:
ssl3_send_alert(s, SSL3_AL_WARNING, al);
return 1;
case SSL_TLSEXT_ERR_NOACK:
s->servername_done = 0;
return 1;
default:
return 1;
}
}
/*
* Parse the extensions in the ClientHello that were collected earlier. Returns
* 1 for success or 0 for failure.
*/
static int tls_parse_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello)
{
int al = -1;
custom_ext_init(&s->cert->srv_ext);
if (tls_scan_clienthello_tlsext(s, hello, &al) <= 0) {
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
}
if (!tls_check_clienthello_tlsext(s)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
return 1;
}
MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
{
int i, al = SSL_AD_INTERNAL_ERROR;
@ -1336,9 +1526,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
s->hit = 0;
/* We need to do this before getting the session */
if (!tls_check_client_ems_support(s, &clienthello)) {
/* Only fails if the extension is malformed */
al = SSL_AD_DECODE_ERROR;
if (!tls_parse_extension(s, TLSEXT_TYPE_extended_master_secret,
clienthello.pre_proc_exts,
clienthello.num_extensions, &al)) {
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
goto f_err;
}
@ -1436,7 +1626,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
}
/* TLS extensions */
if (!ssl_parse_clienthello_tlsext(s, &clienthello)) {
if (!tls_parse_clienthello_tlsext(s, &clienthello)) {
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
goto err;
}

View File

@ -23,7 +23,6 @@
static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, size_t ticklen,
const unsigned char *sess_id, size_t sesslen,
SSL_SESSION **psess);
static int ssl_check_clienthello_tlsext_early(SSL *s);
static int ssl_check_serverhello_tlsext(SSL *s);
SSL3_ENC_METHOD const TLSv1_enc_data = {
@ -262,8 +261,8 @@ int tls1_ec_nid2curve_id(int nid)
* parsed form instead. (However, this would affect binary compatibility
* so cannot happen in the 1.0.x series.)
*/
static int tls1_get_curvelist(SSL *s, int sess,
const unsigned char **pcurves, size_t *num_curves)
int tls1_get_curvelist(SSL *s, int sess, const unsigned char **pcurves,
size_t *num_curves)
{
size_t pcurveslen = 0;
if (sess) {
@ -308,7 +307,7 @@ static int tls1_get_curvelist(SSL *s, int sess,
}
/* See if curve is allowed by security callback */
static int tls_curve_allowed(SSL *s, const unsigned char *curve, int op)
int tls_curve_allowed(SSL *s, const unsigned char *curve, int op)
{
const tls_curve_info *cinfo;
if (curve[0])
@ -1759,41 +1758,6 @@ int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al)
return 1;
}
/*
* Save the ALPN extension in a ClientHello.
* pkt: the contents of the ALPN extension, not including type and length.
* 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(SSL *s, PACKET *pkt, int *al)
{
PACKET protocol_list, save_protocol_list, protocol;
*al = SSL_AD_DECODE_ERROR;
if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
|| PACKET_remaining(&protocol_list) < 2) {
return 0;
}
save_protocol_list = protocol_list;
do {
/* Protocol names can't be empty. */
if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol)
|| PACKET_remaining(&protocol) == 0) {
return 0;
}
} while (PACKET_remaining(&protocol_list) != 0);
if (!PACKET_memdup(&save_protocol_list,
&s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
*al = TLS1_AD_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.
@ -1831,677 +1795,6 @@ static int tls1_alpn_handle_client_hello_late(SSL *s, int *al)
return 1;
}
#ifndef OPENSSL_NO_EC
/*-
* ssl_check_for_safari attempts to fingerprint Safari using OS X
* SecureTransport using the TLS extension block in |hello|.
* Safari, since 10.6, sends exactly these extensions, in this order:
* SNI,
* elliptic_curves
* ec_point_formats
*
* We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
* but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
* Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
* 10.8..10.8.3 (which don't work).
*/
static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
{
unsigned int type;
PACKET sni, tmppkt;
size_t ext_len;
static const unsigned char kSafariExtensionsBlock[] = {
0x00, 0x0a, /* elliptic_curves extension */
0x00, 0x08, /* 8 bytes */
0x00, 0x06, /* 6 bytes of curve ids */
0x00, 0x17, /* P-256 */
0x00, 0x18, /* P-384 */
0x00, 0x19, /* P-521 */
0x00, 0x0b, /* ec_point_formats */
0x00, 0x02, /* 2 bytes */
0x01, /* 1 point format */
0x00, /* uncompressed */
/* The following is only present in TLS 1.2 */
0x00, 0x0d, /* signature_algorithms */
0x00, 0x0c, /* 12 bytes */
0x00, 0x0a, /* 10 bytes */
0x05, 0x01, /* SHA-384/RSA */
0x04, 0x01, /* SHA-256/RSA */
0x02, 0x01, /* SHA-1/RSA */
0x04, 0x03, /* SHA-256/ECDSA */
0x02, 0x03, /* SHA-1/ECDSA */
};
/* Length of the common prefix (first two extensions). */
static const size_t kSafariCommonExtensionsLength = 18;
tmppkt = hello->extensions;
if (!PACKET_forward(&tmppkt, 2)
|| !PACKET_get_net_2(&tmppkt, &type)
|| !PACKET_get_length_prefixed_2(&tmppkt, &sni)) {
return;
}
if (type != TLSEXT_TYPE_server_name)
return;
ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ?
sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength;
s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
ext_len);
}
#endif /* !OPENSSL_NO_EC */
/*
* Process the supported_groups extension if present. Returns success if the
* extension is absent, or if it has been successfully processed.
*
* Returns 1 on success or 0 on failure
*/
static int tls_process_supported_groups(SSL *s, CLIENTHELLO_MSG *hello)
{
#ifndef OPENSSL_NO_EC
PACKET supported_groups_list;
RAW_EXTENSION *suppgroups = tls_get_extension_by_type(hello->pre_proc_exts,
hello->num_extensions,
TLSEXT_TYPE_supported_groups);
if (suppgroups == NULL)
return 1;
/* Each group is 2 bytes and we must have at least 1. */
if (!PACKET_as_length_prefixed_2(&suppgroups->data,
&supported_groups_list)
|| PACKET_remaining(&supported_groups_list) == 0
|| (PACKET_remaining(&supported_groups_list) % 2) != 0) {
return 0;
}
if (!s->hit
&& !PACKET_memdup(&supported_groups_list,
&s->session->tlsext_supportedgroupslist,
&s->session->tlsext_supportedgroupslist_length)) {
return 0;
}
#endif
return 1;
}
/*
* Checks a list of |groups| to determine if the |group_id| is in it. If it is
* and |checkallow| is 1 then additionally check if the group is allowed to be
* used. Returns 1 if the group is in the list (and allowed if |checkallow| is
* 1) or 0 otherwise.
*/
static int check_in_list(SSL *s, unsigned int group_id,
const unsigned char *groups, size_t num_groups,
int checkallow)
{
size_t i;
if (groups == NULL || num_groups == 0)
return 0;
for (i = 0; i < num_groups; i++, groups += 2) {
unsigned int share_id = (groups[0] << 8) | (groups[1]);
if (group_id == share_id
&& (!checkallow || tls_curve_allowed(s, groups,
SSL_SECOP_CURVE_CHECK))) {
break;
}
}
/* If i == num_groups then not in the list */
return i < num_groups;
}
/*
* Process a key_share extension received in the ClientHello. |pkt| contains
* the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
* If a failure occurs then |*al| is set to an appropriate alert value.
*/
static int process_key_share_ext(SSL *s, PACKET *pkt, int *al)
{
unsigned int group_id;
PACKET key_share_list, encoded_pt;
const unsigned char *clntcurves, *srvrcurves;
size_t clnt_num_curves, srvr_num_curves;
int group_nid, found = 0;
unsigned int curve_flags;
/* Sanity check */
if (s->s3->peer_tmp != NULL) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/* Get our list of supported curves */
if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* Get the clients list of supported curves */
if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT,
ERR_R_INTERNAL_ERROR);
return 0;
}
while (PACKET_remaining(&key_share_list) > 0) {
if (!PACKET_get_net_2(&key_share_list, &group_id)
|| !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt)
|| PACKET_remaining(&encoded_pt) == 0) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/*
* If we already found a suitable key_share we loop through the
* rest to verify the structure, but don't process them.
*/
if (found)
continue;
/* Check if this share is in supported_groups sent from client */
if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT,
SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is for a group we can use */
if (!check_in_list(s, group_id, srvrcurves, srvr_num_curves, 1)) {
/* Share not suitable */
continue;
}
group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags);
if (group_nid == 0) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
return 0;
}
if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) {
/* Can happen for some curves, e.g. X25519 */
EVP_PKEY *key = EVP_PKEY_new();
if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, ERR_R_EVP_LIB);
EVP_PKEY_free(key);
return 0;
}
s->s3->peer_tmp = key;
} else {
/* Set up EVP_PKEY with named curve as parameters */
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
if (pctx == NULL
|| EVP_PKEY_paramgen_init(pctx) <= 0
|| EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
group_nid) <= 0
|| EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, ERR_R_EVP_LIB);
EVP_PKEY_CTX_free(pctx);
return 0;
}
EVP_PKEY_CTX_free(pctx);
pctx = NULL;
}
s->s3->group_id = group_id;
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
*al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, SSL_R_BAD_ECPOINT);
return 0;
}
found = 1;
}
return 1;
}
/*
* Loop through all remaining ClientHello extensions that we collected earlier
* and haven't already processed. For each one parse it and update the SSL
* object as required.
*
* Behaviour upon resumption is extension-specific. If the extension has no
* effect during resumption, it is parsed (to verify its format) but otherwise
* ignored.
*
* Returns 1 on success and 0 on failure.
* Upon failure, sets |al| to the appropriate alert.
*/
static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al)
{
size_t loop;
int renegotiate_seen = 0;
*al = SSL_AD_DECODE_ERROR;
s->servername_done = 0;
s->tlsext_status_type = -1;
#ifndef OPENSSL_NO_NEXTPROTONEG
s->s3->next_proto_neg_seen = 0;
#endif
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = NULL;
s->s3->alpn_selected_len = 0;
OPENSSL_free(s->s3->alpn_proposed);
s->s3->alpn_proposed = NULL;
s->s3->alpn_proposed_len = 0;
#ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
ssl_check_for_safari(s, hello);
#endif /* !OPENSSL_NO_EC */
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_sigalgs);
s->s3->tmp.peer_sigalgs = NULL;
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
#ifndef OPENSSL_NO_SRP
OPENSSL_free(s->srp_ctx.login);
s->srp_ctx.login = NULL;
#endif
s->srtp_profile = NULL;
/*
* We process the supported_groups extension first so that is done before
* we get to key_share which needs to use the information in it.
*/
if (!tls_process_supported_groups(s, hello)) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
/*
* We parse all extensions to ensure the ClientHello is well-formed but,
* unless an extension specifies otherwise, we ignore extensions upon
* resumption.
*/
for (loop = 0; loop < hello->num_extensions; loop++) {
RAW_EXTENSION *currext = &hello->pre_proc_exts[loop];
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 0, currext->type,
PACKET_data(&currext->data),
PACKET_remaining(&currext->data),
s->tlsext_debug_arg);
if (currext->type == TLSEXT_TYPE_renegotiate) {
if (!ssl_parse_clienthello_renegotiate_ext(s,
&currext->data, al))
return 0;
renegotiate_seen = 1;
} else if (s->version == SSL3_VERSION) {
}
/*-
* The servername extension is treated as follows:
*
* - Only the hostname type is supported with a maximum length of 255.
* - The servername is rejected if too long or if it contains zeros,
* in which case an fatal alert is generated.
* - The servername field is maintained together with the session cache.
* - When a session is resumed, the servername call back invoked in order
* to allow the application to position itself to the right context.
* - The servername is acknowledged if it is new for a session or when
* it is identical to a previously used for the same session.
* Applications can control the behaviour. They can at any time
* set a 'desirable' servername for a new SSL object. This can be the
* case for example with HTTPS when a Host: header field is received and
* a renegotiation is requested. In this case, a possible servername
* presented in the new client hello is only acknowledged if it matches
* the value of the Host: field.
* - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
* if they provide for changing an explicit servername context for the
* session, i.e. when the session has been established with a servername
* extension.
* - On session reconnect, the servername extension may be absent.
*
*/
else if (currext->type == TLSEXT_TYPE_server_name) {
unsigned int servname_type;
PACKET sni, hostname;
if (!PACKET_as_length_prefixed_2(&currext->data, &sni)
/* ServerNameList must be at least 1 byte long. */
|| PACKET_remaining(&sni) == 0) {
return 0;
}
/*
* Although the server_name extension was intended to be
* extensible to new name types, RFC 4366 defined the
* syntax inextensibility and OpenSSL 1.0.x parses it as
* such.
* RFC 6066 corrected the mistake but adding new name types
* is nevertheless no longer feasible, so act as if no other
* SNI types can exist, to simplify parsing.
*
* Also note that the RFC permits only one SNI value per type,
* i.e., we can only have a single hostname.
*/
if (!PACKET_get_1(&sni, &servname_type)
|| servname_type != TLSEXT_NAMETYPE_host_name
|| !PACKET_as_length_prefixed_2(&sni, &hostname)) {
return 0;
}
if (!s->hit) {
if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
*al = TLS1_AD_UNRECOGNIZED_NAME;
return 0;
}
if (PACKET_contains_zero_byte(&hostname)) {
*al = TLS1_AD_UNRECOGNIZED_NAME;
return 0;
}
if (!PACKET_strndup(&hostname, &s->session->tlsext_hostname)) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
s->servername_done = 1;
} else {
/*
* TODO(openssl-team): if the SNI doesn't match, we MUST
* fall back to a full handshake.
*/
s->servername_done = s->session->tlsext_hostname
&& PACKET_equal(&hostname, s->session->tlsext_hostname,
strlen(s->session->tlsext_hostname));
}
}
#ifndef OPENSSL_NO_SRP
else if (currext->type == TLSEXT_TYPE_srp) {
PACKET srp_I;
if (!PACKET_as_length_prefixed_1(&currext->data, &srp_I))
return 0;
if (PACKET_contains_zero_byte(&srp_I))
return 0;
/*
* TODO(openssl-team): currently, we re-authenticate the user
* upon resumption. Instead, we MUST ignore the login.
*/
if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
}
#endif
#ifndef OPENSSL_NO_EC
else if (currext->type == TLSEXT_TYPE_ec_point_formats) {
PACKET ec_point_format_list;
if (!PACKET_as_length_prefixed_1(&currext->data,
&ec_point_format_list)
|| PACKET_remaining(&ec_point_format_list) == 0) {
return 0;
}
if (!s->hit) {
if (!PACKET_memdup(&ec_point_format_list,
&s->session->tlsext_ecpointformatlist,
&s->
session->tlsext_ecpointformatlist_length)) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
}
}
#endif /* OPENSSL_NO_EC */
else if (currext->type == TLSEXT_TYPE_session_ticket
&& !SSL_IS_TLS13(s)) {
if (s->tls_session_ticket_ext_cb &&
!s->tls_session_ticket_ext_cb(s,
PACKET_data(&currext->data),
PACKET_remaining(&currext->data),
s->tls_session_ticket_ext_cb_arg)) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
} else if (currext->type == TLSEXT_TYPE_signature_algorithms) {
PACKET supported_sig_algs;
if (!PACKET_as_length_prefixed_2(&currext->data,
&supported_sig_algs)
|| (PACKET_remaining(&supported_sig_algs) % 2) != 0
|| PACKET_remaining(&supported_sig_algs) == 0) {
return 0;
}
if (!s->hit) {
if (!tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs),
PACKET_remaining(&supported_sig_algs))) {
return 0;
}
}
} else if (currext->type == TLSEXT_TYPE_status_request) {
if (!PACKET_get_1(&currext->data,
(unsigned int *)&s->tlsext_status_type)) {
return 0;
}
#ifndef OPENSSL_NO_OCSP
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
const unsigned char *ext_data;
PACKET responder_id_list, exts;
if (!PACKET_get_length_prefixed_2
(&currext->data, &responder_id_list))
return 0;
/*
* We remove any OCSP_RESPIDs from a previous handshake
* to prevent unbounded memory growth - CVE-2016-6304
*/
sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids,
OCSP_RESPID_free);
if (PACKET_remaining(&responder_id_list) > 0) {
s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
if (s->tlsext_ocsp_ids == NULL) {
*al = SSL_AD_INTERNAL_ERROR;
return 0;
}
} else {
s->tlsext_ocsp_ids = NULL;
}
while (PACKET_remaining(&responder_id_list) > 0) {
OCSP_RESPID *id;
PACKET responder_id;
const unsigned char *id_data;
if (!PACKET_get_length_prefixed_2(&responder_id_list,
&responder_id)
|| PACKET_remaining(&responder_id) == 0) {
return 0;
}
id_data = PACKET_data(&responder_id);
/* TODO(size_t): Convert d2i_* to size_t */
id = d2i_OCSP_RESPID(NULL, &id_data,
(int)PACKET_remaining(&responder_id));
if (id == NULL)
return 0;
if (id_data != PACKET_end(&responder_id)) {
OCSP_RESPID_free(id);
return 0;
}
if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) {
OCSP_RESPID_free(id);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
}
}
/* Read in request_extensions */
if (!PACKET_as_length_prefixed_2(
&currext->data, &exts))
return 0;
if (PACKET_remaining(&exts) > 0) {
ext_data = PACKET_data(&exts);
sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
X509_EXTENSION_free);
s->tlsext_ocsp_exts =
d2i_X509_EXTENSIONS(NULL, &ext_data,
(int)PACKET_remaining(&exts));
if (s->tlsext_ocsp_exts == NULL
|| ext_data != PACKET_end(&exts)) {
return 0;
}
}
} else
#endif
{
/*
* We don't know what to do with any other type so ignore it.
*/
s->tlsext_status_type = -1;
}
}
#ifndef OPENSSL_NO_NEXTPROTONEG
else if (currext->type == TLSEXT_TYPE_next_proto_neg
&& s->s3->tmp.finish_md_len == 0) {
/*-
* We shouldn't accept this extension on a
* renegotiation.
*
* s->new_session will be set on renegotiation, but we
* probably shouldn't rely that it couldn't be set on
* the initial renegotiation too in certain cases (when
* there's some other reason to disallow resuming an
* earlier session -- the current code won't be doing
* anything like that, but this might change).
*
* A valid sign that there's been a previous handshake
* in this connection is if s->s3->tmp.finish_md_len >
* 0. (We are talking about a check that will happen
* in the Hello protocol round, well before a new
* Finished message could have been computed.)
*/
s->s3->next_proto_neg_seen = 1;
}
#endif
else if (currext->type
== TLSEXT_TYPE_application_layer_protocol_negotiation
&& s->s3->tmp.finish_md_len == 0) {
if (!tls1_alpn_handle_client_hello(s,
&currext->data, al))
return 0;
}
/* session ticket processed earlier */
#ifndef OPENSSL_NO_SRTP
else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
&& currext->type == TLSEXT_TYPE_use_srtp) {
if (ssl_parse_clienthello_use_srtp_ext(s,
&currext->data, al))
return 0;
}
#endif
else if (currext->type == TLSEXT_TYPE_encrypt_then_mac
&& !(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) {
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
} else if (currext->type == TLSEXT_TYPE_key_share
&& SSL_IS_TLS13(s) && !s->hit
&& !process_key_share_ext(s, &currext->data, al)) {
return 0;
}
/*
* Note: extended master secret extension handled in
* tls_check_client_ems_support()
*/
/*
* If this ClientHello extension was unhandled and this is a
* nonresumed connection, check whether the extension is a custom
* TLS Extension (has a custom_srv_ext_record), and if so call the
* callback and record the extension number so that an appropriate
* ServerHello may be later returned.
*/
else if (!s->hit) {
if (custom_ext_parse(s, 1, currext->type,
PACKET_data(&currext->data),
PACKET_remaining(&currext->data), al) <= 0)
return 0;
}
}
/* Need RI if renegotiating */
if (!renegotiate_seen && s->renegotiate &&
!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
*al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT,
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
/*
* This function currently has no state to clean up, so it returns directly.
* If parsing fails at any point, the function returns early.
* The SSL object may be left with partial data from extensions, but it must
* then no longer be used, and clearing it up will free the leftovers.
*/
return 1;
}
int ssl_parse_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello)
{
int al = -1;
custom_ext_init(&s->cert->srv_ext);
if (ssl_scan_clienthello_tlsext(s, hello, &al) <= 0) {
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
}
if (ssl_check_clienthello_tlsext_early(s) <= 0) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* ssl_next_proto_validate validates a Next Protocol Negotiation block. No
@ -2873,49 +2166,6 @@ int ssl_prepare_serverhello_tlsext(SSL *s)
return 1;
}
static int ssl_check_clienthello_tlsext_early(SSL *s)
{
int ret = SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
#ifndef OPENSSL_NO_EC
/*
* 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
if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
ret =
s->ctx->tlsext_servername_callback(s, &al,
s->ctx->tlsext_servername_arg);
else if (s->initial_ctx != NULL
&& s->initial_ctx->tlsext_servername_callback != 0)
ret =
s->initial_ctx->tlsext_servername_callback(s, &al,
s->
initial_ctx->tlsext_servername_arg);
switch (ret) {
case SSL_TLSEXT_ERR_ALERT_FATAL:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return -1;
case SSL_TLSEXT_ERR_ALERT_WARNING:
ssl3_send_alert(s, SSL3_AL_WARNING, al);
return 1;
case SSL_TLSEXT_ERR_NOACK:
s->servername_done = 0;
default:
return 1;
}
}
/* Initialise digests to default values */
void ssl_set_default_md(SSL *s)
{
@ -3196,6 +2446,8 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
if (ticketext == NULL)
return 0;
ticketext->parsed = 1;
size = PACKET_remaining(&ticketext->data);
if (size == 0) {
/*
@ -3237,43 +2489,6 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
}
}
/*
* Sets the extended master secret flag if the extension is present in the
* ClientHello and we can support it
* Returns:
* 1 on success
* 0 on error
*/
int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello)
{
RAW_EXTENSION *emsext;
s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
if (!SSL_IS_DTLS(s) && (s->version < TLS1_VERSION
|| s->version > TLS1_2_VERSION))
return 1;
emsext = tls_get_extension_by_type(hello->pre_proc_exts,
hello->num_extensions,
TLSEXT_TYPE_extended_master_secret);
/*
* No extensions is a success - we have successfully discovered that the
* client doesn't support EMS.
*/
if (emsext == NULL)
return 1;
/* The extensions must always be empty */
if (PACKET_remaining(&emsext->data) != 0)
return 0;
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
return 1;
}
/*-
* tls_decrypt_ticket attempts to decrypt a session ticket.
*

View File

@ -11,44 +11,6 @@
#include <openssl/objects.h>
#include "ssl_locl.h"
/*
* Parse the client's renegotiation binding and abort if it's not right
*/
int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al)
{
unsigned int ilen;
const unsigned char *d;
/* Parse the length byte */
if (!PACKET_get_1(pkt, &ilen)
|| !PACKET_get_bytes(pkt, &d, ilen)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
SSL_R_RENEGOTIATION_ENCODING_ERR);
*al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
/* Check that the extension matches */
if (ilen != s->s3->previous_client_finished_len) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
SSL_R_RENEGOTIATION_MISMATCH);
*al = SSL_AD_HANDSHAKE_FAILURE;
return 0;
}
if (memcmp(d, s->s3->previous_client_finished,
s->s3->previous_client_finished_len)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
SSL_R_RENEGOTIATION_MISMATCH);
*al = SSL_AD_HANDSHAKE_FAILURE;
return 0;
}
s->s3->send_connection_binding = 1;
return 1;
}
/* Add the server's renegotiation binding */
int ssl_add_serverhello_renegotiate_ext(SSL *s, WPACKET *pkt)
{