# 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
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 \
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;
"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),
# 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
__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);
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);
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);
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,
--- /dev/null
+/*
+ * 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 <openssl/ocsp.h>
+#include "../ssl_locl.h"
+#include "statem_locl.h"
+
+static int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al);
+static int tls_parse_clienthello_server_name(SSL *s, PACKET *pkt, int *al);
+#ifndef OPENSSL_NO_SRP
+static int tls_parse_clienthello_srp(SSL *s, PACKET *pkt, int *al);
+#endif
+#ifndef OPENSSL_NO_EC
+static int tls_parse_clienthello_ec_pt_formats(SSL *s, PACKET *pkt, int *al);
+static int tls_parse_clienthello_supported_groups(SSL *s, PACKET *pkt, int *al);
+#endif
+static int tls_parse_clienthello_session_ticket(SSL *s, PACKET *pkt, int *al);
+static int tls_parse_clienthello_sig_algs(SSL *s, PACKET *pkt, int *al);
+static int tls_parse_clienthello_status_request(SSL *s, PACKET *pkt, int *al);
+#ifndef OPENSSL_NO_NEXTPROTONEG
+static int tls_parse_clienthello_npn(SSL *s, PACKET *pkt, int *al);
+#endif
+static int tls_parse_clienthello_alpn(SSL *s, PACKET *pkt, int *al);
+#ifndef OPENSSL_NO_SRTP
+static int tls_parse_clienthello_use_srtp(SSL *s, PACKET *pkt, int *al);
+#endif
+static int tls_parse_clienthello_etm(SSL *s, PACKET *pkt, int *al);
+static int tls_parse_clienthello_key_share(SSL *s, PACKET *pkt, int *al);
+static int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al);
+
+typedef struct {
+ /* The ID for the extension */
+ unsigned int type;
+ int (*server_parse)(SSL *s, PACKET *pkt, int *al);
+ int (*client_parse)(SSL *s, PACKET *pkt, int *al);
+ unsigned int context;
+} EXTENSION_DEFINITION;
+
+static const EXTENSION_DEFINITION ext_defs[] = {
+ {
+ TLSEXT_TYPE_renegotiate,
+ tls_parse_clienthello_renegotiate,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED
+ | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+ {
+ TLSEXT_TYPE_server_name,
+ tls_parse_clienthello_server_name,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
+ | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+ },
+#ifndef OPENSSL_NO_SRP
+ {
+ TLSEXT_TYPE_srp,
+ tls_parse_clienthello_srp,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+#endif
+#ifndef OPENSSL_NO_EC
+ {
+ TLSEXT_TYPE_ec_point_formats,
+ tls_parse_clienthello_ec_pt_formats,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+ {
+ TLSEXT_TYPE_supported_groups,
+ tls_parse_clienthello_supported_groups,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+ },
+#endif
+ {
+ TLSEXT_TYPE_session_ticket,
+ tls_parse_clienthello_session_ticket,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+ {
+ TLSEXT_TYPE_signature_algorithms,
+ tls_parse_clienthello_sig_algs,
+ NULL,
+ EXT_CLIENT_HELLO
+ },
+ {
+ TLSEXT_TYPE_status_request,
+ tls_parse_clienthello_status_request,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_3_CERTIFICATE
+ },
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ {
+ TLSEXT_TYPE_next_proto_neg,
+ tls_parse_clienthello_npn,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+#endif
+ {
+ TLSEXT_TYPE_application_layer_protocol_negotiation,
+ tls_parse_clienthello_alpn,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
+ | EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+ },
+ {
+ TLSEXT_TYPE_use_srtp,
+ tls_parse_clienthello_use_srtp,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
+ | EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY
+ },
+ {
+ TLSEXT_TYPE_encrypt_then_mac,
+ tls_parse_clienthello_etm,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+ {
+ TLSEXT_TYPE_signed_certificate_timestamp,
+ /*
+ * No server side support for this, but can be provided by a custom
+ * extension. This is an exception to the rule that custom extensions
+ * cannot override built in ones.
+ */
+ NULL,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_3_CERTIFICATE
+ },
+ {
+ TLSEXT_TYPE_extended_master_secret,
+ tls_parse_clienthello_ems,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+ {
+ TLSEXT_TYPE_supported_versions,
+ /* Processed inline as part of version selection */
+ NULL,
+ NULL,
+ EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY
+ },
+ {
+ TLSEXT_TYPE_padding,
+ /* We send this, but don't read it */
+ NULL,
+ NULL,
+ EXT_CLIENT_HELLO
+ },
+ {
+ TLSEXT_TYPE_key_share,
+ tls_parse_clienthello_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
+ }
+};
+
+/*
+ * 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;
+
+ if (SSL_IS_DTLS(s)) {
+ if ((ext_defs[i].context & EXT_TLS_ONLY) != 0)
+ return 0;
+ } else if ((ext_defs[i].context & EXT_DTLS_ONLY) != 0) {
+ return 0;
+ }
+
+ return 1;
+ }
+ }
+
+ /* Unknown extension. We allow it */
+ return 1;
+}
+
+/*
+ * Finds an extension definition for the give extension |type|.
+ * Returns 1 if found and stores the definition in |*def|, or returns 0
+ * otherwise.
+ */
+static int find_extension_definition(SSL *s, unsigned int type,
+ const EXTENSION_DEFINITION **def)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(ext_defs); i++) {
+ if (type == ext_defs[i].type) {
+ *def = &ext_defs[i];
+ return 1;
+ }
+ }
+
+ /* Unknown extension */
+ return 0;
+}
+
+/*
+ * 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_zalloc(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;
+}
+
+int tls_parse_all_extensions(SSL *s, RAW_EXTENSION *exts, size_t numexts,
+ int *al)
+{
+ size_t loop;
+
+ for (loop = 0; loop < numexts; loop++) {
+ RAW_EXTENSION *currext = &exts[loop];
+ const EXTENSION_DEFINITION *extdef = NULL;
+ int (*parser)(SSL *s, PACKET *pkt, int *al) = NULL;
+
+ 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);
+
+ /* Skip if we've already parsed this extension */
+ if (currext->parsed)
+ continue;
+
+ currext->parsed = 1;
+
+ parser = NULL;
+ if (find_extension_definition(s, currext->type, &extdef))
+ parser = s->server ? extdef->server_parse : extdef->client_parse;
+
+ if (parser == NULL) {
+ /*
+ * Could be a custom extension. We only allow this if it is a non
+ * resumed session on the server side
+ */
+ if ((!s->hit || !s->server)
+ && custom_ext_parse(s, s->server, currext->type,
+ PACKET_data(&currext->data),
+ PACKET_remaining(&currext->data),
+ al) <= 0)
+ return 0;
+
+ continue;
+ }
+
+ /* Check if this extension is defined for our protocol. If not, skip */
+ if ((SSL_IS_DTLS(s)
+ && (extdef->context & EXT_TLS_IMPLEMENTATION_ONLY) != 0)
+ || (s->version == SSL3_VERSION
+ && (extdef->context & EXT_SSL3_ALLOWED) == 0)
+ || (SSL_IS_TLS13(s)
+ && (extdef->context & EXT_TLS1_2_AND_BELOW_ONLY) != 0)
+ || (!SSL_IS_TLS13(s)
+ && (extdef->context & EXT_TLS1_3_ONLY) != 0)
+ || (s->server && extdef->server_parse == NULL)
+ || (!s->server && extdef->client_parse == NULL))
+ continue;
+
+ if (!parser(s, &currext->data, al))
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Find a specific extension by |type| in the list |exts| containing |numexts|
+ * extensions, and the parse it immediately. Returns 1 on success, or 0 on
+ * failure. If a failure has occurred then |*al| will also be set to the alert
+ * to be sent.
+ */
+int tls_parse_extension(SSL *s, int type, RAW_EXTENSION *exts, size_t numexts,
+ int *al)
+{
+ RAW_EXTENSION *ext = tls_get_extension_by_type(exts, numexts, type);
+
+ if (ext == NULL)
+ return 1;
+
+ return tls_parse_all_extensions(s, ext, 1, al);
+}
+
+
+/*
+ * Parse the client's renegotiation binding and abort if it's not right
+ */
+static int tls_parse_clienthello_renegotiate(SSL *s, PACKET *pkt, int *al)
+{
+ unsigned int ilen;
+ const unsigned char *data;
+
+ /* Parse the length byte */
+ if (!PACKET_get_1(pkt, &ilen)
+ || !PACKET_get_bytes(pkt, &data, 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(data, 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;
+}
+
+static int tls_parse_clienthello_server_name(SSL *s, PACKET *pkt, int *al)
+{
+ unsigned int servname_type;
+ PACKET sni, hostname;
+
+ /*-
+ * 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.
+ *
+ */
+ if (!PACKET_as_length_prefixed_2(pkt, &sni)
+ /* ServerNameList must be at least 1 byte long. */
+ || PACKET_remaining(&sni) == 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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)) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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));
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRP
+static int tls_parse_clienthello_srp(SSL *s, PACKET *pkt, int *al)
+{
+ PACKET srp_I;
+
+ if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
+ || PACKET_contains_zero_byte(&srp_I)) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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;
+ }
+
+ return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+static int tls_parse_clienthello_ec_pt_formats(SSL *s, PACKET *pkt, int *al)
+{
+ PACKET ec_point_format_list;
+
+ if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
+ || PACKET_remaining(&ec_point_format_list) == 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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;
+ }
+ }
+
+ return 1;
+}
+#endif /* OPENSSL_NO_EC */
+
+static int tls_parse_clienthello_session_ticket(SSL *s, PACKET *pkt, int *al)
+{
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, PACKET_data(pkt),
+ PACKET_remaining(pkt),
+ s->tls_session_ticket_ext_cb_arg)) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int tls_parse_clienthello_sig_algs(SSL *s, PACKET *pkt, int *al)
+{
+ PACKET supported_sig_algs;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
+ || (PACKET_remaining(&supported_sig_algs) % 2) != 0
+ || PACKET_remaining(&supported_sig_algs) == 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!s->hit && !tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs),
+ PACKET_remaining(&supported_sig_algs))) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int tls_parse_clienthello_status_request(SSL *s, PACKET *pkt, int *al)
+{
+ if (!PACKET_get_1(pkt, (unsigned int *)&s->tlsext_status_type)) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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 (pkt, &responder_id_list)) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (id_data != PACKET_end(&responder_id)) {
+ OCSP_RESPID_free(id);
+ *al = SSL_AD_DECODE_ERROR;
+ 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(pkt, &exts)) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ }
+ } else
+#endif
+ {
+ /*
+ * We don't know what to do with any other type so ignore it.
+ */
+ s->tlsext_status_type = -1;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+static int tls_parse_clienthello_npn(SSL *s, PACKET *pkt, int *al)
+{
+ if (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;
+ }
+
+ return 1;
+}
+#endif
+
+/*
+ * 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 tls_parse_clienthello_alpn(SSL *s, PACKET *pkt, int *al)
+{
+ PACKET protocol_list, save_protocol_list, protocol;
+
+ if (s->s3->tmp.finish_md_len != 0)
+ return 1;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
+ || PACKET_remaining(&protocol_list) < 2) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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;
+}
+
+#ifndef OPENSSL_NO_SRTP
+static int tls_parse_clienthello_use_srtp(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;
+
+ /* Ignore this if we have no SRTP profiles */
+ if (SSL_get_srtp_profiles(s) == NULL)
+ return 1;
+
+ /* 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_TLS_PARSE_CLIENTHELLO_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ 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_TLS_PARSE_CLIENTHELLO_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /*
+ * 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_TLS_PARSE_CLIENTHELLO_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!PACKET_forward(pkt, mki_len)
+ || PACKET_remaining(pkt)) {
+ SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_USE_SRTP, SSL_R_BAD_SRTP_MKI_VALUE);
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+static int tls_parse_clienthello_etm(SSL *s, PACKET *pkt, int *al)
+{
+ if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
+ s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
+
+ 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 tls_parse_clienthello_key_share(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;
+
+ if (s->hit)
+ return 1;
+
+ /* Sanity check */
+ if (s->s3->peer_tmp != NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE, 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE, 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE, 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE,
+ 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE, 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE,
+ 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE, 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE, 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_TLS_PARSE_CLIENTHELLO_KEY_SHARE, SSL_R_BAD_ECPOINT);
+ return 0;
+ }
+
+ found = 1;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+static int tls_parse_clienthello_supported_groups(SSL *s, PACKET *pkt, int *al)
+{
+ PACKET supported_groups_list;
+
+ /* Each group is 2 bytes and we must have at least 1. */
+ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list)
+ || PACKET_remaining(&supported_groups_list) == 0
+ || (PACKET_remaining(&supported_groups_list) % 2) != 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (!s->hit
+ && !PACKET_memdup(&supported_groups_list,
+ &s->session->tlsext_supportedgroupslist,
+ &s->session->tlsext_supportedgroupslist_length)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+static int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al)
+{
+ /* The extension must always be empty */
+ if (PACKET_remaining(pkt) != 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
+
+ return 1;
+}
+++ /dev/null
-/*
- * 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;
-}
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;
#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 {
__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);
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;
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;
}
}
/* 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;
}
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 = {
* 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) {
}
/* 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])
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.
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
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)
{
if (ticketext == NULL)
return 0;
+ ticketext->parsed = 1;
+
size = PACKET_remaining(&ticketext->data);
if (size == 0) {
/*
}
}
-/*
- * 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.
*
#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)
{