aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/openssl/ssl/statem
diff options
context:
space:
mode:
authordeshevoy <deshevoy@yandex-team.ru>2022-02-10 16:46:56 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:56 +0300
commite988f30484abe5fdeedcc7a5d3c226c01a21800c (patch)
tree0a217b173aabb57b7e51f8a169989b1a3e0309fe /contrib/libs/openssl/ssl/statem
parent33ee501c05d3f24036ae89766a858930ae66c548 (diff)
downloadydb-e988f30484abe5fdeedcc7a5d3c226c01a21800c.tar.gz
Restoring authorship annotation for <deshevoy@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/openssl/ssl/statem')
-rw-r--r--contrib/libs/openssl/ssl/statem/extensions.c3360
-rw-r--r--contrib/libs/openssl/ssl/statem/extensions_clnt.c3930
-rw-r--r--contrib/libs/openssl/ssl/statem/extensions_cust.c1062
-rw-r--r--contrib/libs/openssl/ssl/statem/extensions_srvr.c3876
-rw-r--r--contrib/libs/openssl/ssl/statem/statem.c1940
-rw-r--r--contrib/libs/openssl/ssl/statem/statem.h314
-rw-r--r--contrib/libs/openssl/ssl/statem/statem_clnt.c7656
-rw-r--r--contrib/libs/openssl/ssl/statem/statem_dtls.c2558
-rw-r--r--contrib/libs/openssl/ssl/statem/statem_lib.c4746
-rw-r--r--contrib/libs/openssl/ssl/statem/statem_srvr.c8396
10 files changed, 18919 insertions, 18919 deletions
diff --git a/contrib/libs/openssl/ssl/statem/extensions.c b/contrib/libs/openssl/ssl/statem/extensions.c
index 0f39275baa..01c92c22f1 100644
--- a/contrib/libs/openssl/ssl/statem/extensions.c
+++ b/contrib/libs/openssl/ssl/statem/extensions.c
@@ -1,1033 +1,1033 @@
-/*
+/*
* Copyright 2016-2021 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 <string.h>
-#include "internal/nelem.h"
-#include "internal/cryptlib.h"
+ *
+ * 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 <string.h>
+#include "internal/nelem.h"
+#include "internal/cryptlib.h"
#include "../ssl_local.h"
#include "statem_local.h"
-#include "internal/cryptlib.h"
-
-static int final_renegotiate(SSL *s, unsigned int context, int sent);
-static int init_server_name(SSL *s, unsigned int context);
-static int final_server_name(SSL *s, unsigned int context, int sent);
-#ifndef OPENSSL_NO_EC
+#include "internal/cryptlib.h"
+
+static int final_renegotiate(SSL *s, unsigned int context, int sent);
+static int init_server_name(SSL *s, unsigned int context);
+static int final_server_name(SSL *s, unsigned int context, int sent);
+#ifndef OPENSSL_NO_EC
static int init_ec_point_formats(SSL *s, unsigned int context);
-static int final_ec_pt_formats(SSL *s, unsigned int context, int sent);
-#endif
-static int init_session_ticket(SSL *s, unsigned int context);
-#ifndef OPENSSL_NO_OCSP
-static int init_status_request(SSL *s, unsigned int context);
-#endif
-#ifndef OPENSSL_NO_NEXTPROTONEG
-static int init_npn(SSL *s, unsigned int context);
-#endif
-static int init_alpn(SSL *s, unsigned int context);
-static int final_alpn(SSL *s, unsigned int context, int sent);
-static int init_sig_algs_cert(SSL *s, unsigned int context);
-static int init_sig_algs(SSL *s, unsigned int context);
-static int init_certificate_authorities(SSL *s, unsigned int context);
-static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
- unsigned int context,
- X509 *x,
- size_t chainidx);
-static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx);
-#ifndef OPENSSL_NO_SRP
-static int init_srp(SSL *s, unsigned int context);
-#endif
-static int init_etm(SSL *s, unsigned int context);
-static int init_ems(SSL *s, unsigned int context);
-static int final_ems(SSL *s, unsigned int context, int sent);
-static int init_psk_kex_modes(SSL *s, unsigned int context);
-#ifndef OPENSSL_NO_EC
-static int final_key_share(SSL *s, unsigned int context, int sent);
-#endif
-#ifndef OPENSSL_NO_SRTP
-static int init_srtp(SSL *s, unsigned int context);
-#endif
-static int final_sig_algs(SSL *s, unsigned int context, int sent);
-static int final_early_data(SSL *s, unsigned int context, int sent);
-static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
-static int init_post_handshake_auth(SSL *s, unsigned int context);
+static int final_ec_pt_formats(SSL *s, unsigned int context, int sent);
+#endif
+static int init_session_ticket(SSL *s, unsigned int context);
+#ifndef OPENSSL_NO_OCSP
+static int init_status_request(SSL *s, unsigned int context);
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+static int init_npn(SSL *s, unsigned int context);
+#endif
+static int init_alpn(SSL *s, unsigned int context);
+static int final_alpn(SSL *s, unsigned int context, int sent);
+static int init_sig_algs_cert(SSL *s, unsigned int context);
+static int init_sig_algs(SSL *s, unsigned int context);
+static int init_certificate_authorities(SSL *s, unsigned int context);
+static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
+ unsigned int context,
+ X509 *x,
+ size_t chainidx);
+static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx);
+#ifndef OPENSSL_NO_SRP
+static int init_srp(SSL *s, unsigned int context);
+#endif
+static int init_etm(SSL *s, unsigned int context);
+static int init_ems(SSL *s, unsigned int context);
+static int final_ems(SSL *s, unsigned int context, int sent);
+static int init_psk_kex_modes(SSL *s, unsigned int context);
+#ifndef OPENSSL_NO_EC
+static int final_key_share(SSL *s, unsigned int context, int sent);
+#endif
+#ifndef OPENSSL_NO_SRTP
+static int init_srtp(SSL *s, unsigned int context);
+#endif
+static int final_sig_algs(SSL *s, unsigned int context, int sent);
+static int final_early_data(SSL *s, unsigned int context, int sent);
+static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
+static int init_post_handshake_auth(SSL *s, unsigned int context);
static int final_psk(SSL *s, unsigned int context, int sent);
-
-/* Structure to define a built-in extension */
-typedef struct extensions_definition_st {
- /* The defined type for the extension */
- unsigned int type;
- /*
- * The context that this extension applies to, e.g. what messages and
- * protocol versions
- */
- unsigned int context;
- /*
- * Initialise extension before parsing. Always called for relevant contexts
- * even if extension not present
- */
- int (*init)(SSL *s, unsigned int context);
- /* Parse extension sent from client to server */
- int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx);
- /* Parse extension send from server to client */
- int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx);
- /* Construct extension sent from server to client */
- EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
- /* Construct extension sent from client to server */
- EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
- /*
- * Finalise extension after parsing. Always called where an extensions was
- * initialised even if the extension was not present. |sent| is set to 1 if
- * the extension was seen, or 0 otherwise.
- */
- int (*final)(SSL *s, unsigned int context, int sent);
-} EXTENSION_DEFINITION;
-
-/*
- * Definitions of all built-in extensions. NOTE: Changes in the number or order
- * of these extensions should be mirrored with equivalent changes to the
+
+/* Structure to define a built-in extension */
+typedef struct extensions_definition_st {
+ /* The defined type for the extension */
+ unsigned int type;
+ /*
+ * The context that this extension applies to, e.g. what messages and
+ * protocol versions
+ */
+ unsigned int context;
+ /*
+ * Initialise extension before parsing. Always called for relevant contexts
+ * even if extension not present
+ */
+ int (*init)(SSL *s, unsigned int context);
+ /* Parse extension sent from client to server */
+ int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx);
+ /* Parse extension send from server to client */
+ int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx);
+ /* Construct extension sent from server to client */
+ EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx);
+ /* Construct extension sent from client to server */
+ EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx);
+ /*
+ * Finalise extension after parsing. Always called where an extensions was
+ * initialised even if the extension was not present. |sent| is set to 1 if
+ * the extension was seen, or 0 otherwise.
+ */
+ int (*final)(SSL *s, unsigned int context, int sent);
+} EXTENSION_DEFINITION;
+
+/*
+ * Definitions of all built-in extensions. NOTE: Changes in the number or order
+ * of these extensions should be mirrored with equivalent changes to the
* indexes ( TLSEXT_IDX_* ) defined in ssl_local.h.
- * Each extension has an initialiser, a client and
- * server side parser and a finaliser. The initialiser is called (if the
- * extension is relevant to the given context) even if we did not see the
- * extension in the message that we received. The parser functions are only
- * called if we see the extension in the message. The finalisers are always
- * called if the initialiser was called.
- * There are also server and client side constructor functions which are always
- * called during message construction if the extension is relevant for the
- * given context.
- * The initialisation, parsing, finalisation and construction functions are
- * always called in the order defined in this list. Some extensions may depend
- * on others having been processed first, so the order of this list is
- * significant.
- * The extension context is defined by a series of flags which specify which
- * messages the extension is relevant to. These flags also specify whether the
- * extension is relevant to a particular protocol or protocol version.
- *
- * TODO(TLS1.3): Make sure we have a test to check the consistency of these
- *
- * NOTE: WebSphere Application Server 7+ cannot handle empty extensions at
- * the end, keep these extensions before signature_algorithm.
- */
-#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL }
-static const EXTENSION_DEFINITION ext_defs[] = {
- {
- TLSEXT_TYPE_renegotiate,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_SSL3_ALLOWED | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
- NULL, tls_parse_ctos_renegotiate, tls_parse_stoc_renegotiate,
- tls_construct_stoc_renegotiate, tls_construct_ctos_renegotiate,
- final_renegotiate
- },
- {
- TLSEXT_TYPE_server_name,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- init_server_name,
- tls_parse_ctos_server_name, tls_parse_stoc_server_name,
- tls_construct_stoc_server_name, tls_construct_ctos_server_name,
- final_server_name
- },
- {
- TLSEXT_TYPE_max_fragment_length,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- NULL, tls_parse_ctos_maxfragmentlen, tls_parse_stoc_maxfragmentlen,
- tls_construct_stoc_maxfragmentlen, tls_construct_ctos_maxfragmentlen,
- final_maxfragmentlen
- },
-#ifndef OPENSSL_NO_SRP
- {
- TLSEXT_TYPE_srp,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
- init_srp, tls_parse_ctos_srp, NULL, NULL, tls_construct_ctos_srp, NULL
- },
-#else
- INVALID_EXTENSION,
-#endif
-#ifndef OPENSSL_NO_EC
- {
- TLSEXT_TYPE_ec_point_formats,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ * Each extension has an initialiser, a client and
+ * server side parser and a finaliser. The initialiser is called (if the
+ * extension is relevant to the given context) even if we did not see the
+ * extension in the message that we received. The parser functions are only
+ * called if we see the extension in the message. The finalisers are always
+ * called if the initialiser was called.
+ * There are also server and client side constructor functions which are always
+ * called during message construction if the extension is relevant for the
+ * given context.
+ * The initialisation, parsing, finalisation and construction functions are
+ * always called in the order defined in this list. Some extensions may depend
+ * on others having been processed first, so the order of this list is
+ * significant.
+ * The extension context is defined by a series of flags which specify which
+ * messages the extension is relevant to. These flags also specify whether the
+ * extension is relevant to a particular protocol or protocol version.
+ *
+ * TODO(TLS1.3): Make sure we have a test to check the consistency of these
+ *
+ * NOTE: WebSphere Application Server 7+ cannot handle empty extensions at
+ * the end, keep these extensions before signature_algorithm.
+ */
+#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL }
+static const EXTENSION_DEFINITION ext_defs[] = {
+ {
+ TLSEXT_TYPE_renegotiate,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_SSL3_ALLOWED | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ NULL, tls_parse_ctos_renegotiate, tls_parse_stoc_renegotiate,
+ tls_construct_stoc_renegotiate, tls_construct_ctos_renegotiate,
+ final_renegotiate
+ },
+ {
+ TLSEXT_TYPE_server_name,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
+ init_server_name,
+ tls_parse_ctos_server_name, tls_parse_stoc_server_name,
+ tls_construct_stoc_server_name, tls_construct_ctos_server_name,
+ final_server_name
+ },
+ {
+ TLSEXT_TYPE_max_fragment_length,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
+ NULL, tls_parse_ctos_maxfragmentlen, tls_parse_stoc_maxfragmentlen,
+ tls_construct_stoc_maxfragmentlen, tls_construct_ctos_maxfragmentlen,
+ final_maxfragmentlen
+ },
+#ifndef OPENSSL_NO_SRP
+ {
+ TLSEXT_TYPE_srp,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ init_srp, tls_parse_ctos_srp, NULL, NULL, tls_construct_ctos_srp, NULL
+ },
+#else
+ INVALID_EXTENSION,
+#endif
+#ifndef OPENSSL_NO_EC
+ {
+ TLSEXT_TYPE_ec_point_formats,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
init_ec_point_formats, tls_parse_ctos_ec_pt_formats, tls_parse_stoc_ec_pt_formats,
- tls_construct_stoc_ec_pt_formats, tls_construct_ctos_ec_pt_formats,
- final_ec_pt_formats
- },
- {
- /*
- * "supported_groups" is spread across several specifications.
- * It was originally specified as "elliptic_curves" in RFC 4492,
- * and broadened to include named FFDH groups by RFC 7919.
- * Both RFCs 4492 and 7919 do not include a provision for the server
- * to indicate to the client the complete list of groups supported
- * by the server, with the server instead just indicating the
- * selected group for this connection in the ServerKeyExchange
- * message. TLS 1.3 adds a scheme for the server to indicate
- * to the client its list of supported groups in the
- * EncryptedExtensions message, but none of the relevant
- * specifications permit sending supported_groups in the ServerHello.
- * Nonetheless (possibly due to the close proximity to the
- * "ec_point_formats" extension, which is allowed in the ServerHello),
- * there are several servers that send this extension in the
- * ServerHello anyway. Up to and including the 1.1.0 release,
- * we did not check for the presence of nonpermitted extensions,
- * so to avoid a regression, we must permit this extension in the
- * TLS 1.2 ServerHello as well.
- *
- * Note that there is no tls_parse_stoc_supported_groups function,
- * so we do not perform any additional parsing, validation, or
- * processing on the server's group list -- this is just a minimal
- * change to preserve compatibility with these misbehaving servers.
- */
- TLSEXT_TYPE_supported_groups,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
- | SSL_EXT_TLS1_2_SERVER_HELLO,
- NULL, tls_parse_ctos_supported_groups, NULL,
- tls_construct_stoc_supported_groups,
- tls_construct_ctos_supported_groups, NULL
- },
-#else
- INVALID_EXTENSION,
- INVALID_EXTENSION,
-#endif
- {
- TLSEXT_TYPE_session_ticket,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
- init_session_ticket, tls_parse_ctos_session_ticket,
- tls_parse_stoc_session_ticket, tls_construct_stoc_session_ticket,
- tls_construct_ctos_session_ticket, NULL
- },
-#ifndef OPENSSL_NO_OCSP
- {
- TLSEXT_TYPE_status_request,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
- init_status_request, tls_parse_ctos_status_request,
- tls_parse_stoc_status_request, tls_construct_stoc_status_request,
- tls_construct_ctos_status_request, NULL
- },
+ tls_construct_stoc_ec_pt_formats, tls_construct_ctos_ec_pt_formats,
+ final_ec_pt_formats
+ },
+ {
+ /*
+ * "supported_groups" is spread across several specifications.
+ * It was originally specified as "elliptic_curves" in RFC 4492,
+ * and broadened to include named FFDH groups by RFC 7919.
+ * Both RFCs 4492 and 7919 do not include a provision for the server
+ * to indicate to the client the complete list of groups supported
+ * by the server, with the server instead just indicating the
+ * selected group for this connection in the ServerKeyExchange
+ * message. TLS 1.3 adds a scheme for the server to indicate
+ * to the client its list of supported groups in the
+ * EncryptedExtensions message, but none of the relevant
+ * specifications permit sending supported_groups in the ServerHello.
+ * Nonetheless (possibly due to the close proximity to the
+ * "ec_point_formats" extension, which is allowed in the ServerHello),
+ * there are several servers that send this extension in the
+ * ServerHello anyway. Up to and including the 1.1.0 release,
+ * we did not check for the presence of nonpermitted extensions,
+ * so to avoid a regression, we must permit this extension in the
+ * TLS 1.2 ServerHello as well.
+ *
+ * Note that there is no tls_parse_stoc_supported_groups function,
+ * so we do not perform any additional parsing, validation, or
+ * processing on the server's group list -- this is just a minimal
+ * change to preserve compatibility with these misbehaving servers.
+ */
+ TLSEXT_TYPE_supported_groups,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+ | SSL_EXT_TLS1_2_SERVER_HELLO,
+ NULL, tls_parse_ctos_supported_groups, NULL,
+ tls_construct_stoc_supported_groups,
+ tls_construct_ctos_supported_groups, NULL
+ },
+#else
+ INVALID_EXTENSION,
+ INVALID_EXTENSION,
+#endif
+ {
+ TLSEXT_TYPE_session_ticket,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ init_session_ticket, tls_parse_ctos_session_ticket,
+ tls_parse_stoc_session_ticket, tls_construct_stoc_session_ticket,
+ tls_construct_ctos_session_ticket, NULL
+ },
+#ifndef OPENSSL_NO_OCSP
+ {
+ TLSEXT_TYPE_status_request,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
+ init_status_request, tls_parse_ctos_status_request,
+ tls_parse_stoc_status_request, tls_construct_stoc_status_request,
+ tls_construct_ctos_status_request, NULL
+ },
+#else
+ INVALID_EXTENSION,
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ {
+ TLSEXT_TYPE_next_proto_neg,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ init_npn, tls_parse_ctos_npn, tls_parse_stoc_npn,
+ tls_construct_stoc_next_proto_neg, tls_construct_ctos_npn, NULL
+ },
+#else
+ INVALID_EXTENSION,
+#endif
+ {
+ /*
+ * Must appear in this list after server_name so that finalisation
+ * happens after server_name callbacks
+ */
+ TLSEXT_TYPE_application_layer_protocol_negotiation,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
+ init_alpn, tls_parse_ctos_alpn, tls_parse_stoc_alpn,
+ tls_construct_stoc_alpn, tls_construct_ctos_alpn, final_alpn
+ },
+#ifndef OPENSSL_NO_SRTP
+ {
+ TLSEXT_TYPE_use_srtp,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS | SSL_EXT_DTLS_ONLY,
+ init_srtp, tls_parse_ctos_use_srtp, tls_parse_stoc_use_srtp,
+ tls_construct_stoc_use_srtp, tls_construct_ctos_use_srtp, NULL
+ },
+#else
+ INVALID_EXTENSION,
+#endif
+ {
+ TLSEXT_TYPE_encrypt_then_mac,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ init_etm, tls_parse_ctos_etm, tls_parse_stoc_etm,
+ tls_construct_stoc_etm, tls_construct_ctos_etm, NULL
+ },
+#ifndef OPENSSL_NO_CT
+ {
+ TLSEXT_TYPE_signed_certificate_timestamp,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
+ NULL,
+ /*
+ * 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, tls_parse_stoc_sct, NULL, tls_construct_ctos_sct, NULL
+ },
+#else
+ INVALID_EXTENSION,
+#endif
+ {
+ TLSEXT_TYPE_extended_master_secret,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ init_ems, tls_parse_ctos_ems, tls_parse_stoc_ems,
+ tls_construct_stoc_ems, tls_construct_ctos_ems, final_ems
+ },
+ {
+ TLSEXT_TYPE_signature_algorithms_cert,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
+ init_sig_algs_cert, tls_parse_ctos_sig_algs_cert,
+ tls_parse_ctos_sig_algs_cert,
+ /* We do not generate signature_algorithms_cert at present. */
+ NULL, NULL, NULL
+ },
+ {
+ TLSEXT_TYPE_post_handshake_auth,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY,
+ init_post_handshake_auth,
+ tls_parse_ctos_post_handshake_auth, NULL,
+ NULL, tls_construct_ctos_post_handshake_auth,
+ NULL,
+ },
+ {
+ TLSEXT_TYPE_signature_algorithms,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
+ init_sig_algs, tls_parse_ctos_sig_algs,
+ tls_parse_ctos_sig_algs, tls_construct_ctos_sig_algs,
+ tls_construct_ctos_sig_algs, final_sig_algs
+ },
+ {
+ TLSEXT_TYPE_supported_versions,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
+ | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY,
+ NULL,
+ /* Processed inline as part of version selection */
+ NULL, tls_parse_stoc_supported_versions,
+ tls_construct_stoc_supported_versions,
+ tls_construct_ctos_supported_versions, NULL
+ },
+ {
+ TLSEXT_TYPE_psk_kex_modes,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY
+ | SSL_EXT_TLS1_3_ONLY,
+ init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL,
+ tls_construct_ctos_psk_kex_modes, NULL
+ },
+#ifndef OPENSSL_NO_EC
+ {
+ /*
+ * Must be in this list after supported_groups. We need that to have
+ * been parsed before we do this one.
+ */
+ TLSEXT_TYPE_key_share,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
+ | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY
+ | SSL_EXT_TLS1_3_ONLY,
+ NULL, tls_parse_ctos_key_share, tls_parse_stoc_key_share,
+ tls_construct_stoc_key_share, tls_construct_ctos_key_share,
+ final_key_share
+ },
#else
INVALID_EXTENSION,
-#endif
-#ifndef OPENSSL_NO_NEXTPROTONEG
- {
- TLSEXT_TYPE_next_proto_neg,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
- init_npn, tls_parse_ctos_npn, tls_parse_stoc_npn,
- tls_construct_stoc_next_proto_neg, tls_construct_ctos_npn, NULL
- },
-#else
- INVALID_EXTENSION,
-#endif
- {
- /*
- * Must appear in this list after server_name so that finalisation
- * happens after server_name callbacks
- */
- TLSEXT_TYPE_application_layer_protocol_negotiation,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- init_alpn, tls_parse_ctos_alpn, tls_parse_stoc_alpn,
- tls_construct_stoc_alpn, tls_construct_ctos_alpn, final_alpn
- },
-#ifndef OPENSSL_NO_SRTP
- {
- TLSEXT_TYPE_use_srtp,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS | SSL_EXT_DTLS_ONLY,
- init_srtp, tls_parse_ctos_use_srtp, tls_parse_stoc_use_srtp,
- tls_construct_stoc_use_srtp, tls_construct_ctos_use_srtp, NULL
- },
-#else
- INVALID_EXTENSION,
-#endif
- {
- TLSEXT_TYPE_encrypt_then_mac,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
- init_etm, tls_parse_ctos_etm, tls_parse_stoc_etm,
- tls_construct_stoc_etm, tls_construct_ctos_etm, NULL
- },
-#ifndef OPENSSL_NO_CT
- {
- TLSEXT_TYPE_signed_certificate_timestamp,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
- NULL,
- /*
- * 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, tls_parse_stoc_sct, NULL, tls_construct_ctos_sct, NULL
- },
-#else
- INVALID_EXTENSION,
-#endif
- {
- TLSEXT_TYPE_extended_master_secret,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
- init_ems, tls_parse_ctos_ems, tls_parse_stoc_ems,
- tls_construct_stoc_ems, tls_construct_ctos_ems, final_ems
- },
- {
- TLSEXT_TYPE_signature_algorithms_cert,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
- init_sig_algs_cert, tls_parse_ctos_sig_algs_cert,
- tls_parse_ctos_sig_algs_cert,
- /* We do not generate signature_algorithms_cert at present. */
- NULL, NULL, NULL
- },
- {
- TLSEXT_TYPE_post_handshake_auth,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY,
- init_post_handshake_auth,
- tls_parse_ctos_post_handshake_auth, NULL,
- NULL, tls_construct_ctos_post_handshake_auth,
- NULL,
- },
- {
- TLSEXT_TYPE_signature_algorithms,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
- init_sig_algs, tls_parse_ctos_sig_algs,
- tls_parse_ctos_sig_algs, tls_construct_ctos_sig_algs,
- tls_construct_ctos_sig_algs, final_sig_algs
- },
- {
- TLSEXT_TYPE_supported_versions,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
- | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY,
- NULL,
- /* Processed inline as part of version selection */
- NULL, tls_parse_stoc_supported_versions,
- tls_construct_stoc_supported_versions,
- tls_construct_ctos_supported_versions, NULL
- },
- {
- TLSEXT_TYPE_psk_kex_modes,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY
- | SSL_EXT_TLS1_3_ONLY,
- init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL,
- tls_construct_ctos_psk_kex_modes, NULL
- },
-#ifndef OPENSSL_NO_EC
- {
- /*
- * Must be in this list after supported_groups. We need that to have
- * been parsed before we do this one.
- */
- TLSEXT_TYPE_key_share,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
- | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY
- | SSL_EXT_TLS1_3_ONLY,
- NULL, tls_parse_ctos_key_share, tls_parse_stoc_key_share,
- tls_construct_stoc_key_share, tls_construct_ctos_key_share,
- final_key_share
- },
-#else
- INVALID_EXTENSION,
-#endif
- {
- /* Must be after key_share */
- TLSEXT_TYPE_cookie,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
- | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
- NULL, tls_parse_ctos_cookie, tls_parse_stoc_cookie,
- tls_construct_stoc_cookie, tls_construct_ctos_cookie, NULL
- },
- {
- /*
- * Special unsolicited ServerHello extension only used when
- * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but
- * ignore it.
- */
- TLSEXT_TYPE_cryptopro_bug,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
- NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL
- },
- {
- TLSEXT_TYPE_early_data,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
- | SSL_EXT_TLS1_3_NEW_SESSION_TICKET | SSL_EXT_TLS1_3_ONLY,
- NULL, tls_parse_ctos_early_data, tls_parse_stoc_early_data,
- tls_construct_stoc_early_data, tls_construct_ctos_early_data,
- final_early_data
- },
- {
- TLSEXT_TYPE_certificate_authorities,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
- | SSL_EXT_TLS1_3_ONLY,
- init_certificate_authorities,
- tls_parse_certificate_authorities, tls_parse_certificate_authorities,
- tls_construct_certificate_authorities,
- tls_construct_certificate_authorities, NULL,
- },
- {
- /* Must be immediately before pre_shared_key */
- TLSEXT_TYPE_padding,
- SSL_EXT_CLIENT_HELLO,
- NULL,
- /* We send this, but don't read it */
- NULL, NULL, NULL, tls_construct_ctos_padding, NULL
- },
- {
- /* Required by the TLSv1.3 spec to always be the last extension */
- TLSEXT_TYPE_psk,
- SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
- | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
- NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk,
+#endif
+ {
+ /* Must be after key_share */
+ TLSEXT_TYPE_cookie,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
+ | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
+ NULL, tls_parse_ctos_cookie, tls_parse_stoc_cookie,
+ tls_construct_stoc_cookie, tls_construct_ctos_cookie, NULL
+ },
+ {
+ /*
+ * Special unsolicited ServerHello extension only used when
+ * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but
+ * ignore it.
+ */
+ TLSEXT_TYPE_cryptopro_bug,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+ NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL
+ },
+ {
+ TLSEXT_TYPE_early_data,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+ | SSL_EXT_TLS1_3_NEW_SESSION_TICKET | SSL_EXT_TLS1_3_ONLY,
+ NULL, tls_parse_ctos_early_data, tls_parse_stoc_early_data,
+ tls_construct_stoc_early_data, tls_construct_ctos_early_data,
+ final_early_data
+ },
+ {
+ TLSEXT_TYPE_certificate_authorities,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
+ | SSL_EXT_TLS1_3_ONLY,
+ init_certificate_authorities,
+ tls_parse_certificate_authorities, tls_parse_certificate_authorities,
+ tls_construct_certificate_authorities,
+ tls_construct_certificate_authorities, NULL,
+ },
+ {
+ /* Must be immediately before pre_shared_key */
+ TLSEXT_TYPE_padding,
+ SSL_EXT_CLIENT_HELLO,
+ NULL,
+ /* We send this, but don't read it */
+ NULL, NULL, NULL, tls_construct_ctos_padding, NULL
+ },
+ {
+ /* Required by the TLSv1.3 spec to always be the last extension */
+ TLSEXT_TYPE_psk,
+ SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
+ | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
+ NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk,
tls_construct_ctos_psk, final_psk
- }
-};
-
-/* Check whether an extension's context matches the current context */
-static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
-{
- /* Check we're allowed to use this extension in this context */
- if ((thisctx & extctx) == 0)
- return 0;
-
- if (SSL_IS_DTLS(s)) {
- if ((extctx & SSL_EXT_TLS_ONLY) != 0)
- return 0;
- } else if ((extctx & SSL_EXT_DTLS_ONLY) != 0) {
- return 0;
- }
-
- return 1;
-}
-
-int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts)
-{
- size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset;
- RAW_EXTENSION *thisext;
- unsigned int context;
- ENDPOINT role = ENDPOINT_BOTH;
-
- if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0)
- role = ENDPOINT_SERVER;
- else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
- role = ENDPOINT_CLIENT;
-
- /* Calculate the number of extensions in the extensions list */
- num_exts = builtin_num + s->cert->custext.meths_count;
-
- for (thisext = exts, i = 0; i < num_exts; i++, thisext++) {
- if (!thisext->present)
- continue;
-
- if (i < builtin_num) {
- context = ext_defs[i].context;
- } else {
- custom_ext_method *meth = NULL;
-
- meth = custom_ext_find(&s->cert->custext, role, thisext->type,
- &offset);
- if (!ossl_assert(meth != NULL))
- return 0;
- context = meth->context;
- }
-
- if (!validate_context(s, context, thisctx))
- return 0;
- }
-
- return 1;
-}
-
-/*
- * 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. If returning 1 then |*found| is set to
- * the definition for the extension we found.
- */
-static int verify_extension(SSL *s, unsigned int context, unsigned int type,
- custom_ext_methods *meths, RAW_EXTENSION *rawexlist,
- RAW_EXTENSION **found)
-{
- size_t i;
- size_t builtin_num = OSSL_NELEM(ext_defs);
- const EXTENSION_DEFINITION *thisext;
-
- for (i = 0, thisext = ext_defs; i < builtin_num; i++, thisext++) {
- if (type == thisext->type) {
- if (!validate_context(s, thisext->context, context))
- return 0;
-
- *found = &rawexlist[i];
- return 1;
- }
- }
-
- /* Check the custom extensions */
- if (meths != NULL) {
- size_t offset = 0;
- ENDPOINT role = ENDPOINT_BOTH;
- custom_ext_method *meth = NULL;
-
- if ((context & SSL_EXT_CLIENT_HELLO) != 0)
- role = ENDPOINT_SERVER;
- else if ((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
- role = ENDPOINT_CLIENT;
-
- meth = custom_ext_find(meths, role, type, &offset);
- if (meth != NULL) {
- if (!validate_context(s, meth->context, context))
- return 0;
- *found = &rawexlist[offset + builtin_num];
- return 1;
- }
- }
-
- /* Unknown extension. We allow it */
- *found = NULL;
- return 1;
-}
-
-/*
- * Check whether the context defined for an extension |extctx| means whether
- * the extension is relevant for the current context |thisctx| or not. Returns
- * 1 if the extension is relevant for this context, and 0 otherwise
- */
-int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
-{
- int is_tls13;
-
- /*
- * For HRR we haven't selected the version yet but we know it will be
- * TLSv1.3
- */
- if ((thisctx & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
- is_tls13 = 1;
- else
- is_tls13 = SSL_IS_TLS13(s);
-
- if ((SSL_IS_DTLS(s)
- && (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0)
- || (s->version == SSL3_VERSION
- && (extctx & SSL_EXT_SSL3_ALLOWED) == 0)
- /*
- * Note that SSL_IS_TLS13() means "TLS 1.3 has been negotiated",
- * which is never true when generating the ClientHello.
- * However, version negotiation *has* occurred by the time the
- * ClientHello extensions are being parsed.
- * Be careful to allow TLS 1.3-only extensions when generating
- * the ClientHello.
- */
- || (is_tls13 && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0)
- || (!is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0
- && (thisctx & SSL_EXT_CLIENT_HELLO) == 0)
- || (s->server && !is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0)
- || (s->hit && (extctx & SSL_EXT_IGNORE_ON_RESUMPTION) != 0))
- return 0;
- 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| on success. We don't actually process the content of the
- * extensions yet, except to check their types. This function also runs the
- * initialiser functions for all known extensions if |init| is nonzero (whether
- * we have collected them or not). If successful the caller is responsible for
- * freeing the contents of |*res|.
- *
- * 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
- * found, or an internal error occurred. We only check duplicates for
- * extensions that we know about. We ignore others.
- */
-int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
- RAW_EXTENSION **res, size_t *len, int init)
-{
- PACKET extensions = *packet;
- size_t i = 0;
- size_t num_exts;
- custom_ext_methods *exts = &s->cert->custext;
- RAW_EXTENSION *raw_extensions = NULL;
- const EXTENSION_DEFINITION *thisexd;
-
- *res = NULL;
-
- /*
- * Initialise server side custom extensions. Client side is done during
- * construction of extensions for the ClientHello.
- */
- if ((context & SSL_EXT_CLIENT_HELLO) != 0)
- custom_ext_init(&s->cert->custext);
-
- num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0);
- raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions));
- if (raw_extensions == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- i = 0;
- while (PACKET_remaining(&extensions) > 0) {
- unsigned int type, idx;
- PACKET extension;
- RAW_EXTENSION *thisex;
-
- if (!PACKET_get_net_2(&extensions, &type) ||
- !PACKET_get_length_prefixed_2(&extensions, &extension)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
- SSL_R_BAD_EXTENSION);
- goto err;
- }
- /*
- * Verify this extension is allowed. We only check duplicates for
- * extensions that we recognise. We also have a special case for the
- * PSK extension, which must be the last one in the ClientHello.
- */
- if (!verify_extension(s, context, type, exts, raw_extensions, &thisex)
- || (thisex != NULL && thisex->present == 1)
- || (type == TLSEXT_TYPE_psk
- && (context & SSL_EXT_CLIENT_HELLO) != 0
- && PACKET_remaining(&extensions) != 0)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS,
- SSL_R_BAD_EXTENSION);
- goto err;
- }
- idx = thisex - raw_extensions;
- /*-
- * Check that we requested this extension (if appropriate). Requests can
- * be sent in the ClientHello and CertificateRequest. Unsolicited
- * extensions can be sent in the NewSessionTicket. We only do this for
- * the built-in extensions. Custom extensions have a different but
- * similar check elsewhere.
- * Special cases:
- * - The HRR cookie extension is unsolicited
- * - The renegotiate extension is unsolicited (the client signals
- * support via an SCSV)
- * - The signed_certificate_timestamp extension can be provided by a
- * custom extension or by the built-in version. We let the extension
- * itself handle unsolicited response checks.
- */
- if (idx < OSSL_NELEM(ext_defs)
- && (context & (SSL_EXT_CLIENT_HELLO
- | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
- | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) == 0
- && type != TLSEXT_TYPE_cookie
- && type != TLSEXT_TYPE_renegotiate
- && type != TLSEXT_TYPE_signed_certificate_timestamp
- && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0
-#ifndef OPENSSL_NO_GOST
- && !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
- && type == TLSEXT_TYPE_cryptopro_bug)
-#endif
- ) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
- SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
- goto err;
- }
- if (thisex != NULL) {
- thisex->data = extension;
- thisex->present = 1;
- thisex->type = type;
- thisex->received_order = i++;
- if (s->ext.debug_cb)
- s->ext.debug_cb(s, !s->server, thisex->type,
- PACKET_data(&thisex->data),
- PACKET_remaining(&thisex->data),
- s->ext.debug_arg);
- }
- }
-
- if (init) {
- /*
- * Initialise all known extensions relevant to this context,
- * whether we have found them or not
- */
- for (thisexd = ext_defs, i = 0; i < OSSL_NELEM(ext_defs);
- i++, thisexd++) {
- if (thisexd->init != NULL && (thisexd->context & context) != 0
- && extension_is_relevant(s, thisexd->context, context)
- && !thisexd->init(s, context)) {
- /* SSLfatal() already called */
- goto err;
- }
- }
- }
-
- *res = raw_extensions;
- if (len != NULL)
- *len = num_exts;
- return 1;
-
- err:
- OPENSSL_free(raw_extensions);
- return 0;
-}
-
-/*
- * Runs the parser for a given extension with index |idx|. |exts| contains the
- * list of all parsed extensions previously collected by
- * tls_collect_extensions(). The parser is only run if it is applicable for the
- * given |context| and the parser has not already been run. If this is for a
- * Certificate message, then we also provide the parser with the relevant
- * Certificate |x| and its position in the |chainidx| with 0 being the first
- * Certificate. Returns 1 on success or 0 on failure. If an extension is not
- * present this counted as success.
- */
-int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
- RAW_EXTENSION *exts, X509 *x, size_t chainidx)
-{
- RAW_EXTENSION *currext = &exts[idx];
- int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx) = NULL;
-
- /* Skip if the extension is not present */
- if (!currext->present)
- return 1;
-
- /* Skip if we've already parsed this extension */
- if (currext->parsed)
- return 1;
-
- currext->parsed = 1;
-
- if (idx < OSSL_NELEM(ext_defs)) {
- /* We are handling a built-in extension */
- const EXTENSION_DEFINITION *extdef = &ext_defs[idx];
-
- /* Check if extension is defined for our protocol. If not, skip */
- if (!extension_is_relevant(s, extdef->context, context))
- return 1;
-
- parser = s->server ? extdef->parse_ctos : extdef->parse_stoc;
-
- if (parser != NULL)
- return parser(s, &currext->data, context, x, chainidx);
-
- /*
- * If the parser is NULL we fall through to the custom extension
- * processing
- */
- }
-
- /* Parse custom extensions */
- return custom_ext_parse(s, context, currext->type,
- PACKET_data(&currext->data),
- PACKET_remaining(&currext->data),
- x, chainidx);
-}
-
-/*
- * Parse all remaining extensions that have not yet been parsed. Also calls the
- * finalisation for all extensions at the end if |fin| is nonzero, whether we
- * collected them or not. Returns 1 for success or 0 for failure. If we are
- * working on a Certificate message then we also pass the Certificate |x| and
- * its position in the |chainidx|, with 0 being the first certificate.
- */
-int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
- size_t chainidx, int fin)
-{
- size_t i, numexts = OSSL_NELEM(ext_defs);
- const EXTENSION_DEFINITION *thisexd;
-
- /* Calculate the number of extensions in the extensions list */
- numexts += s->cert->custext.meths_count;
-
- /* Parse each extension in turn */
- for (i = 0; i < numexts; i++) {
- if (!tls_parse_extension(s, i, context, exts, x, chainidx)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
-
- if (fin) {
- /*
- * Finalise all known extensions relevant to this context,
- * whether we have found them or not
- */
- for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs);
- i++, thisexd++) {
- if (thisexd->final != NULL && (thisexd->context & context) != 0
- && !thisexd->final(s, context, exts[i].present)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
- }
-
- return 1;
-}
-
-int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
- int max_version)
-{
- /* Skip if not relevant for our context */
- if ((extctx & thisctx) == 0)
- return 0;
-
- /* Check if this extension is defined for our protocol. If not, skip */
- if (!extension_is_relevant(s, extctx, thisctx)
- || ((extctx & SSL_EXT_TLS1_3_ONLY) != 0
- && (thisctx & SSL_EXT_CLIENT_HELLO) != 0
- && (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION)))
- return 0;
-
- return 1;
-}
-
-/*
- * Construct all the extensions relevant to the current |context| and write
- * them to |pkt|. If this is an extension for a Certificate in a Certificate
- * message, then |x| will be set to the Certificate we are handling, and
- * |chainidx| will indicate the position in the chainidx we are processing (with
- * 0 being the first in the chain). Returns 1 on success or 0 on failure. On a
- * failure construction stops at the first extension to fail to construct.
- */
-int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- size_t i;
- int min_version, max_version = 0, reason;
- const EXTENSION_DEFINITION *thisexd;
-
- if (!WPACKET_start_sub_packet_u16(pkt)
- /*
- * If extensions are of zero length then we don't even add the
- * extensions length bytes to a ClientHello/ServerHello
- * (for non-TLSv1.3).
- */
- || ((context &
- (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
- && !WPACKET_set_flags(pkt,
- WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
- reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
- if (reason != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
- reason);
- return 0;
- }
- }
-
- /* Add custom extensions first */
- if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
- /* On the server side with initialise during ClientHello parsing */
- custom_ext_init(&s->cert->custext);
- }
- if (!custom_ext_add(s, context, pkt, x, chainidx, max_version)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) {
- EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx);
- EXT_RETURN ret;
-
- /* Skip if not relevant for our context */
- if (!should_add_extension(s, thisexd->context, context, max_version))
- continue;
-
- construct = s->server ? thisexd->construct_stoc
- : thisexd->construct_ctos;
-
- if (construct == NULL)
- continue;
-
- ret = construct(s, pkt, context, x, chainidx);
- if (ret == EXT_RETURN_FAIL) {
- /* SSLfatal() already called */
- return 0;
- }
- if (ret == EXT_RETURN_SENT
- && (context & (SSL_EXT_CLIENT_HELLO
- | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
- | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) != 0)
- s->ext.extflags[i] |= SSL_EXT_FLAG_SENT;
- }
-
- if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Built in extension finalisation and initialisation functions. All initialise
- * or finalise the associated extension type for the given |context|. For
- * finalisers |sent| is set to 1 if we saw the extension during parsing, and 0
- * otherwise. These functions return 1 on success or 0 on failure.
- */
-
-static int final_renegotiate(SSL *s, unsigned int context, int sent)
-{
- if (!s->server) {
- /*
- * Check if we can connect to a server that doesn't support safe
- * renegotiation
- */
- if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
- && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
- && !sent) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
- SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
- return 0;
- }
-
- return 1;
- }
-
- /* Need RI if renegotiating */
- if (s->renegotiate
- && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
- && !sent) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
- SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
- return 0;
- }
-
-
- return 1;
-}
-
-static int init_server_name(SSL *s, unsigned int context)
-{
- if (s->server) {
- s->servername_done = 0;
-
- OPENSSL_free(s->ext.hostname);
- s->ext.hostname = NULL;
- }
-
- return 1;
-}
-
-static int final_server_name(SSL *s, unsigned int context, int sent)
-{
- int ret = SSL_TLSEXT_ERR_NOACK;
- int altmp = SSL_AD_UNRECOGNIZED_NAME;
- int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
-
- if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (s->ctx->ext.servername_cb != NULL)
- ret = s->ctx->ext.servername_cb(s, &altmp,
- s->ctx->ext.servername_arg);
- else if (s->session_ctx->ext.servername_cb != NULL)
- ret = s->session_ctx->ext.servername_cb(s, &altmp,
- s->session_ctx->ext.servername_arg);
-
- /*
- * For servers, propagate the SNI hostname from the temporary
- * storage in the SSL to the persistent SSL_SESSION, now that we
- * know we accepted it.
- * Clients make this copy when parsing the server's response to
- * the extension, which is when they find out that the negotiation
- * was successful.
- */
- if (s->server) {
+ }
+};
+
+/* Check whether an extension's context matches the current context */
+static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
+{
+ /* Check we're allowed to use this extension in this context */
+ if ((thisctx & extctx) == 0)
+ return 0;
+
+ if (SSL_IS_DTLS(s)) {
+ if ((extctx & SSL_EXT_TLS_ONLY) != 0)
+ return 0;
+ } else if ((extctx & SSL_EXT_DTLS_ONLY) != 0) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts)
+{
+ size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset;
+ RAW_EXTENSION *thisext;
+ unsigned int context;
+ ENDPOINT role = ENDPOINT_BOTH;
+
+ if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0)
+ role = ENDPOINT_SERVER;
+ else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
+ role = ENDPOINT_CLIENT;
+
+ /* Calculate the number of extensions in the extensions list */
+ num_exts = builtin_num + s->cert->custext.meths_count;
+
+ for (thisext = exts, i = 0; i < num_exts; i++, thisext++) {
+ if (!thisext->present)
+ continue;
+
+ if (i < builtin_num) {
+ context = ext_defs[i].context;
+ } else {
+ custom_ext_method *meth = NULL;
+
+ meth = custom_ext_find(&s->cert->custext, role, thisext->type,
+ &offset);
+ if (!ossl_assert(meth != NULL))
+ return 0;
+ context = meth->context;
+ }
+
+ if (!validate_context(s, context, thisctx))
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * 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. If returning 1 then |*found| is set to
+ * the definition for the extension we found.
+ */
+static int verify_extension(SSL *s, unsigned int context, unsigned int type,
+ custom_ext_methods *meths, RAW_EXTENSION *rawexlist,
+ RAW_EXTENSION **found)
+{
+ size_t i;
+ size_t builtin_num = OSSL_NELEM(ext_defs);
+ const EXTENSION_DEFINITION *thisext;
+
+ for (i = 0, thisext = ext_defs; i < builtin_num; i++, thisext++) {
+ if (type == thisext->type) {
+ if (!validate_context(s, thisext->context, context))
+ return 0;
+
+ *found = &rawexlist[i];
+ return 1;
+ }
+ }
+
+ /* Check the custom extensions */
+ if (meths != NULL) {
+ size_t offset = 0;
+ ENDPOINT role = ENDPOINT_BOTH;
+ custom_ext_method *meth = NULL;
+
+ if ((context & SSL_EXT_CLIENT_HELLO) != 0)
+ role = ENDPOINT_SERVER;
+ else if ((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
+ role = ENDPOINT_CLIENT;
+
+ meth = custom_ext_find(meths, role, type, &offset);
+ if (meth != NULL) {
+ if (!validate_context(s, meth->context, context))
+ return 0;
+ *found = &rawexlist[offset + builtin_num];
+ return 1;
+ }
+ }
+
+ /* Unknown extension. We allow it */
+ *found = NULL;
+ return 1;
+}
+
+/*
+ * Check whether the context defined for an extension |extctx| means whether
+ * the extension is relevant for the current context |thisctx| or not. Returns
+ * 1 if the extension is relevant for this context, and 0 otherwise
+ */
+int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
+{
+ int is_tls13;
+
+ /*
+ * For HRR we haven't selected the version yet but we know it will be
+ * TLSv1.3
+ */
+ if ((thisctx & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
+ is_tls13 = 1;
+ else
+ is_tls13 = SSL_IS_TLS13(s);
+
+ if ((SSL_IS_DTLS(s)
+ && (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0)
+ || (s->version == SSL3_VERSION
+ && (extctx & SSL_EXT_SSL3_ALLOWED) == 0)
+ /*
+ * Note that SSL_IS_TLS13() means "TLS 1.3 has been negotiated",
+ * which is never true when generating the ClientHello.
+ * However, version negotiation *has* occurred by the time the
+ * ClientHello extensions are being parsed.
+ * Be careful to allow TLS 1.3-only extensions when generating
+ * the ClientHello.
+ */
+ || (is_tls13 && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0)
+ || (!is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0
+ && (thisctx & SSL_EXT_CLIENT_HELLO) == 0)
+ || (s->server && !is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0)
+ || (s->hit && (extctx & SSL_EXT_IGNORE_ON_RESUMPTION) != 0))
+ return 0;
+ 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| on success. We don't actually process the content of the
+ * extensions yet, except to check their types. This function also runs the
+ * initialiser functions for all known extensions if |init| is nonzero (whether
+ * we have collected them or not). If successful the caller is responsible for
+ * freeing the contents of |*res|.
+ *
+ * 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
+ * found, or an internal error occurred. We only check duplicates for
+ * extensions that we know about. We ignore others.
+ */
+int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
+ RAW_EXTENSION **res, size_t *len, int init)
+{
+ PACKET extensions = *packet;
+ size_t i = 0;
+ size_t num_exts;
+ custom_ext_methods *exts = &s->cert->custext;
+ RAW_EXTENSION *raw_extensions = NULL;
+ const EXTENSION_DEFINITION *thisexd;
+
+ *res = NULL;
+
+ /*
+ * Initialise server side custom extensions. Client side is done during
+ * construction of extensions for the ClientHello.
+ */
+ if ((context & SSL_EXT_CLIENT_HELLO) != 0)
+ custom_ext_init(&s->cert->custext);
+
+ num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0);
+ raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions));
+ if (raw_extensions == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ i = 0;
+ while (PACKET_remaining(&extensions) > 0) {
+ unsigned int type, idx;
+ PACKET extension;
+ RAW_EXTENSION *thisex;
+
+ if (!PACKET_get_net_2(&extensions, &type) ||
+ !PACKET_get_length_prefixed_2(&extensions, &extension)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
+ SSL_R_BAD_EXTENSION);
+ goto err;
+ }
+ /*
+ * Verify this extension is allowed. We only check duplicates for
+ * extensions that we recognise. We also have a special case for the
+ * PSK extension, which must be the last one in the ClientHello.
+ */
+ if (!verify_extension(s, context, type, exts, raw_extensions, &thisex)
+ || (thisex != NULL && thisex->present == 1)
+ || (type == TLSEXT_TYPE_psk
+ && (context & SSL_EXT_CLIENT_HELLO) != 0
+ && PACKET_remaining(&extensions) != 0)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS,
+ SSL_R_BAD_EXTENSION);
+ goto err;
+ }
+ idx = thisex - raw_extensions;
+ /*-
+ * Check that we requested this extension (if appropriate). Requests can
+ * be sent in the ClientHello and CertificateRequest. Unsolicited
+ * extensions can be sent in the NewSessionTicket. We only do this for
+ * the built-in extensions. Custom extensions have a different but
+ * similar check elsewhere.
+ * Special cases:
+ * - The HRR cookie extension is unsolicited
+ * - The renegotiate extension is unsolicited (the client signals
+ * support via an SCSV)
+ * - The signed_certificate_timestamp extension can be provided by a
+ * custom extension or by the built-in version. We let the extension
+ * itself handle unsolicited response checks.
+ */
+ if (idx < OSSL_NELEM(ext_defs)
+ && (context & (SSL_EXT_CLIENT_HELLO
+ | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
+ | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) == 0
+ && type != TLSEXT_TYPE_cookie
+ && type != TLSEXT_TYPE_renegotiate
+ && type != TLSEXT_TYPE_signed_certificate_timestamp
+ && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0
+#ifndef OPENSSL_NO_GOST
+ && !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
+ && type == TLSEXT_TYPE_cryptopro_bug)
+#endif
+ ) {
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
+ SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
+ goto err;
+ }
+ if (thisex != NULL) {
+ thisex->data = extension;
+ thisex->present = 1;
+ thisex->type = type;
+ thisex->received_order = i++;
+ if (s->ext.debug_cb)
+ s->ext.debug_cb(s, !s->server, thisex->type,
+ PACKET_data(&thisex->data),
+ PACKET_remaining(&thisex->data),
+ s->ext.debug_arg);
+ }
+ }
+
+ if (init) {
+ /*
+ * Initialise all known extensions relevant to this context,
+ * whether we have found them or not
+ */
+ for (thisexd = ext_defs, i = 0; i < OSSL_NELEM(ext_defs);
+ i++, thisexd++) {
+ if (thisexd->init != NULL && (thisexd->context & context) != 0
+ && extension_is_relevant(s, thisexd->context, context)
+ && !thisexd->init(s, context)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+ }
+
+ *res = raw_extensions;
+ if (len != NULL)
+ *len = num_exts;
+ return 1;
+
+ err:
+ OPENSSL_free(raw_extensions);
+ return 0;
+}
+
+/*
+ * Runs the parser for a given extension with index |idx|. |exts| contains the
+ * list of all parsed extensions previously collected by
+ * tls_collect_extensions(). The parser is only run if it is applicable for the
+ * given |context| and the parser has not already been run. If this is for a
+ * Certificate message, then we also provide the parser with the relevant
+ * Certificate |x| and its position in the |chainidx| with 0 being the first
+ * Certificate. Returns 1 on success or 0 on failure. If an extension is not
+ * present this counted as success.
+ */
+int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
+ RAW_EXTENSION *exts, X509 *x, size_t chainidx)
+{
+ RAW_EXTENSION *currext = &exts[idx];
+ int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx) = NULL;
+
+ /* Skip if the extension is not present */
+ if (!currext->present)
+ return 1;
+
+ /* Skip if we've already parsed this extension */
+ if (currext->parsed)
+ return 1;
+
+ currext->parsed = 1;
+
+ if (idx < OSSL_NELEM(ext_defs)) {
+ /* We are handling a built-in extension */
+ const EXTENSION_DEFINITION *extdef = &ext_defs[idx];
+
+ /* Check if extension is defined for our protocol. If not, skip */
+ if (!extension_is_relevant(s, extdef->context, context))
+ return 1;
+
+ parser = s->server ? extdef->parse_ctos : extdef->parse_stoc;
+
+ if (parser != NULL)
+ return parser(s, &currext->data, context, x, chainidx);
+
+ /*
+ * If the parser is NULL we fall through to the custom extension
+ * processing
+ */
+ }
+
+ /* Parse custom extensions */
+ return custom_ext_parse(s, context, currext->type,
+ PACKET_data(&currext->data),
+ PACKET_remaining(&currext->data),
+ x, chainidx);
+}
+
+/*
+ * Parse all remaining extensions that have not yet been parsed. Also calls the
+ * finalisation for all extensions at the end if |fin| is nonzero, whether we
+ * collected them or not. Returns 1 for success or 0 for failure. If we are
+ * working on a Certificate message then we also pass the Certificate |x| and
+ * its position in the |chainidx|, with 0 being the first certificate.
+ */
+int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
+ size_t chainidx, int fin)
+{
+ size_t i, numexts = OSSL_NELEM(ext_defs);
+ const EXTENSION_DEFINITION *thisexd;
+
+ /* Calculate the number of extensions in the extensions list */
+ numexts += s->cert->custext.meths_count;
+
+ /* Parse each extension in turn */
+ for (i = 0; i < numexts; i++) {
+ if (!tls_parse_extension(s, i, context, exts, x, chainidx)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+
+ if (fin) {
+ /*
+ * Finalise all known extensions relevant to this context,
+ * whether we have found them or not
+ */
+ for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs);
+ i++, thisexd++) {
+ if (thisexd->final != NULL && (thisexd->context & context) != 0
+ && !thisexd->final(s, context, exts[i].present)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
+ int max_version)
+{
+ /* Skip if not relevant for our context */
+ if ((extctx & thisctx) == 0)
+ return 0;
+
+ /* Check if this extension is defined for our protocol. If not, skip */
+ if (!extension_is_relevant(s, extctx, thisctx)
+ || ((extctx & SSL_EXT_TLS1_3_ONLY) != 0
+ && (thisctx & SSL_EXT_CLIENT_HELLO) != 0
+ && (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION)))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Construct all the extensions relevant to the current |context| and write
+ * them to |pkt|. If this is an extension for a Certificate in a Certificate
+ * message, then |x| will be set to the Certificate we are handling, and
+ * |chainidx| will indicate the position in the chainidx we are processing (with
+ * 0 being the first in the chain). Returns 1 on success or 0 on failure. On a
+ * failure construction stops at the first extension to fail to construct.
+ */
+int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ size_t i;
+ int min_version, max_version = 0, reason;
+ const EXTENSION_DEFINITION *thisexd;
+
+ if (!WPACKET_start_sub_packet_u16(pkt)
+ /*
+ * If extensions are of zero length then we don't even add the
+ * extensions length bytes to a ClientHello/ServerHello
+ * (for non-TLSv1.3).
+ */
+ || ((context &
+ (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
+ && !WPACKET_set_flags(pkt,
+ WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
+ reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
+ if (reason != 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
+ reason);
+ return 0;
+ }
+ }
+
+ /* Add custom extensions first */
+ if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
+ /* On the server side with initialise during ClientHello parsing */
+ custom_ext_init(&s->cert->custext);
+ }
+ if (!custom_ext_add(s, context, pkt, x, chainidx, max_version)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) {
+ EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx);
+ EXT_RETURN ret;
+
+ /* Skip if not relevant for our context */
+ if (!should_add_extension(s, thisexd->context, context, max_version))
+ continue;
+
+ construct = s->server ? thisexd->construct_stoc
+ : thisexd->construct_ctos;
+
+ if (construct == NULL)
+ continue;
+
+ ret = construct(s, pkt, context, x, chainidx);
+ if (ret == EXT_RETURN_FAIL) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ if (ret == EXT_RETURN_SENT
+ && (context & (SSL_EXT_CLIENT_HELLO
+ | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
+ | SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) != 0)
+ s->ext.extflags[i] |= SSL_EXT_FLAG_SENT;
+ }
+
+ if (!WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Built in extension finalisation and initialisation functions. All initialise
+ * or finalise the associated extension type for the given |context|. For
+ * finalisers |sent| is set to 1 if we saw the extension during parsing, and 0
+ * otherwise. These functions return 1 on success or 0 on failure.
+ */
+
+static int final_renegotiate(SSL *s, unsigned int context, int sent)
+{
+ if (!s->server) {
+ /*
+ * Check if we can connect to a server that doesn't support safe
+ * renegotiation
+ */
+ if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
+ && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
+ && !sent) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /* Need RI if renegotiating */
+ if (s->renegotiate
+ && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
+ && !sent) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ return 0;
+ }
+
+
+ return 1;
+}
+
+static int init_server_name(SSL *s, unsigned int context)
+{
+ if (s->server) {
+ s->servername_done = 0;
+
+ OPENSSL_free(s->ext.hostname);
+ s->ext.hostname = NULL;
+ }
+
+ return 1;
+}
+
+static int final_server_name(SSL *s, unsigned int context, int sent)
+{
+ int ret = SSL_TLSEXT_ERR_NOACK;
+ int altmp = SSL_AD_UNRECOGNIZED_NAME;
+ int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
+
+ if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (s->ctx->ext.servername_cb != NULL)
+ ret = s->ctx->ext.servername_cb(s, &altmp,
+ s->ctx->ext.servername_arg);
+ else if (s->session_ctx->ext.servername_cb != NULL)
+ ret = s->session_ctx->ext.servername_cb(s, &altmp,
+ s->session_ctx->ext.servername_arg);
+
+ /*
+ * For servers, propagate the SNI hostname from the temporary
+ * storage in the SSL to the persistent SSL_SESSION, now that we
+ * know we accepted it.
+ * Clients make this copy when parsing the server's response to
+ * the extension, which is when they find out that the negotiation
+ * was successful.
+ */
+ if (s->server) {
if (sent && ret == SSL_TLSEXT_ERR_OK && !s->hit) {
- /* Only store the hostname in the session if we accepted it. */
- OPENSSL_free(s->session->ext.hostname);
- s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
- if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- }
- }
- }
-
- /*
- * If we switched contexts (whether here or in the client_hello callback),
- * move the sess_accept increment from the session_ctx to the new
- * context, to avoid the confusing situation of having sess_accept_good
- * exceed sess_accept (zero) for the new context.
- */
+ /* Only store the hostname in the session if we accepted it. */
+ OPENSSL_free(s->session->ext.hostname);
+ s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
+ if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ }
+ }
+ }
+
+ /*
+ * If we switched contexts (whether here or in the client_hello callback),
+ * move the sess_accept increment from the session_ctx to the new
+ * context, to avoid the confusing situation of having sess_accept_good
+ * exceed sess_accept (zero) for the new context.
+ */
if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx
&& s->hello_retry_request == SSL_HRR_NONE) {
- tsan_counter(&s->ctx->stats.sess_accept);
- tsan_decr(&s->session_ctx->stats.sess_accept);
- }
-
- /*
- * If we're expecting to send a ticket, and tickets were previously enabled,
- * and now tickets are disabled, then turn off expected ticket.
- * Also, if this is not a resumption, create a new session ID
- */
- if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected
- && was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) {
- s->ext.ticket_expected = 0;
- if (!s->hit) {
- SSL_SESSION* ss = SSL_get_session(s);
-
- if (ss != NULL) {
- OPENSSL_free(ss->ext.tick);
- ss->ext.tick = NULL;
- ss->ext.ticklen = 0;
- ss->ext.tick_lifetime_hint = 0;
- ss->ext.tick_age_add = 0;
- if (!ssl_generate_session_id(s, ss)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- } else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- }
-
- switch (ret) {
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
- return 0;
-
- case SSL_TLSEXT_ERR_ALERT_WARNING:
- /* TLSv1.3 doesn't have warning alerts so we suppress this */
- if (!SSL_IS_TLS13(s))
- ssl3_send_alert(s, SSL3_AL_WARNING, altmp);
- s->servername_done = 0;
- return 1;
-
- case SSL_TLSEXT_ERR_NOACK:
+ tsan_counter(&s->ctx->stats.sess_accept);
+ tsan_decr(&s->session_ctx->stats.sess_accept);
+ }
+
+ /*
+ * If we're expecting to send a ticket, and tickets were previously enabled,
+ * and now tickets are disabled, then turn off expected ticket.
+ * Also, if this is not a resumption, create a new session ID
+ */
+ if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected
+ && was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) {
+ s->ext.ticket_expected = 0;
+ if (!s->hit) {
+ SSL_SESSION* ss = SSL_get_session(s);
+
+ if (ss != NULL) {
+ OPENSSL_free(ss->ext.tick);
+ ss->ext.tick = NULL;
+ ss->ext.ticklen = 0;
+ ss->ext.tick_lifetime_hint = 0;
+ ss->ext.tick_age_add = 0;
+ if (!ssl_generate_session_id(s, ss)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ }
+
+ switch (ret) {
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
+ return 0;
+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ /* TLSv1.3 doesn't have warning alerts so we suppress this */
+ if (!SSL_IS_TLS13(s))
+ ssl3_send_alert(s, SSL3_AL_WARNING, altmp);
s->servername_done = 0;
- return 1;
-
- default:
- return 1;
- }
-}
-
-#ifndef OPENSSL_NO_EC
+ return 1;
+
+ case SSL_TLSEXT_ERR_NOACK:
+ s->servername_done = 0;
+ return 1;
+
+ default:
+ return 1;
+ }
+}
+
+#ifndef OPENSSL_NO_EC
static int init_ec_point_formats(SSL *s, unsigned int context)
{
OPENSSL_free(s->ext.peer_ecpointformats);
@@ -1037,163 +1037,163 @@ static int init_ec_point_formats(SSL *s, unsigned int context)
return 1;
}
-static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
-{
- unsigned long alg_k, alg_a;
-
- if (s->server)
- return 1;
-
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
- /*
- * If we are client and using an elliptic curve cryptography cipher
- * suite, then if server returns an EC point formats lists extension it
- * must contain uncompressed.
- */
- if (s->ext.ecpointformats != NULL
- && s->ext.ecpointformats_len > 0
+static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
+{
+ unsigned long alg_k, alg_a;
+
+ if (s->server)
+ return 1;
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ /*
+ * If we are client and using an elliptic curve cryptography cipher
+ * suite, then if server returns an EC point formats lists extension it
+ * must contain uncompressed.
+ */
+ if (s->ext.ecpointformats != NULL
+ && s->ext.ecpointformats_len > 0
&& s->ext.peer_ecpointformats != NULL
&& s->ext.peer_ecpointformats_len > 0
- && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
- /* we are using an ECC cipher */
- size_t i;
+ && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
+ /* we are using an ECC cipher */
+ size_t i;
unsigned char *list = s->ext.peer_ecpointformats;
-
+
for (i = 0; i < s->ext.peer_ecpointformats_len; i++) {
- if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed)
- break;
- }
+ if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed)
+ break;
+ }
if (i == s->ext.peer_ecpointformats_len) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS,
- SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
- return 0;
- }
- }
-
- return 1;
-}
-#endif
-
-static int init_session_ticket(SSL *s, unsigned int context)
-{
- if (!s->server)
- s->ext.ticket_expected = 0;
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_OCSP
-static int init_status_request(SSL *s, unsigned int context)
-{
- if (s->server) {
- s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
- } else {
- /*
- * Ensure we get sensible values passed to tlsext_status_cb in the event
- * that we don't receive a status message
- */
- OPENSSL_free(s->ext.ocsp.resp);
- s->ext.ocsp.resp = NULL;
- s->ext.ocsp.resp_len = 0;
- }
-
- return 1;
-}
-#endif
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
-static int init_npn(SSL *s, unsigned int context)
-{
- s->s3->npn_seen = 0;
-
- return 1;
-}
-#endif
-
-static int init_alpn(SSL *s, unsigned int context)
-{
- OPENSSL_free(s->s3->alpn_selected);
- s->s3->alpn_selected = NULL;
- s->s3->alpn_selected_len = 0;
- if (s->server) {
- OPENSSL_free(s->s3->alpn_proposed);
- s->s3->alpn_proposed = NULL;
- s->s3->alpn_proposed_len = 0;
- }
- return 1;
-}
-
-static int final_alpn(SSL *s, unsigned int context, int sent)
-{
- if (!s->server && !sent && s->session->ext.alpn_selected != NULL)
- s->ext.early_data_ok = 0;
-
- if (!s->server || !SSL_IS_TLS13(s))
- return 1;
-
- /*
- * Call alpn_select callback if needed. Has to be done after SNI and
- * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
- * we also have to do this before we decide whether to accept early_data.
- * In TLSv1.3 we've already negotiated our cipher so we do this call now.
- * For < TLSv1.3 we defer it until after cipher negotiation.
- *
- * On failure SSLfatal() already called.
- */
- return tls_handle_alpn(s);
-}
-
-static int init_sig_algs(SSL *s, unsigned int context)
-{
- /* Clear any signature algorithms extension received */
- OPENSSL_free(s->s3->tmp.peer_sigalgs);
- s->s3->tmp.peer_sigalgs = NULL;
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS,
+ SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+static int init_session_ticket(SSL *s, unsigned int context)
+{
+ if (!s->server)
+ s->ext.ticket_expected = 0;
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_OCSP
+static int init_status_request(SSL *s, unsigned int context)
+{
+ if (s->server) {
+ s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
+ } else {
+ /*
+ * Ensure we get sensible values passed to tlsext_status_cb in the event
+ * that we don't receive a status message
+ */
+ OPENSSL_free(s->ext.ocsp.resp);
+ s->ext.ocsp.resp = NULL;
+ s->ext.ocsp.resp_len = 0;
+ }
+
+ return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+static int init_npn(SSL *s, unsigned int context)
+{
+ s->s3->npn_seen = 0;
+
+ return 1;
+}
+#endif
+
+static int init_alpn(SSL *s, unsigned int context)
+{
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+ s->s3->alpn_selected_len = 0;
+ if (s->server) {
+ OPENSSL_free(s->s3->alpn_proposed);
+ s->s3->alpn_proposed = NULL;
+ s->s3->alpn_proposed_len = 0;
+ }
+ return 1;
+}
+
+static int final_alpn(SSL *s, unsigned int context, int sent)
+{
+ if (!s->server && !sent && s->session->ext.alpn_selected != NULL)
+ s->ext.early_data_ok = 0;
+
+ if (!s->server || !SSL_IS_TLS13(s))
+ return 1;
+
+ /*
+ * Call alpn_select callback if needed. Has to be done after SNI and
+ * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
+ * we also have to do this before we decide whether to accept early_data.
+ * In TLSv1.3 we've already negotiated our cipher so we do this call now.
+ * For < TLSv1.3 we defer it until after cipher negotiation.
+ *
+ * On failure SSLfatal() already called.
+ */
+ return tls_handle_alpn(s);
+}
+
+static int init_sig_algs(SSL *s, unsigned int context)
+{
+ /* Clear any signature algorithms extension received */
+ OPENSSL_free(s->s3->tmp.peer_sigalgs);
+ s->s3->tmp.peer_sigalgs = NULL;
s->s3->tmp.peer_sigalgslen = 0;
-
- return 1;
-}
-
-static int init_sig_algs_cert(SSL *s, unsigned int context)
-{
- /* Clear any signature algorithms extension received */
- OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
- s->s3->tmp.peer_cert_sigalgs = NULL;
+
+ return 1;
+}
+
+static int init_sig_algs_cert(SSL *s, unsigned int context)
+{
+ /* Clear any signature algorithms extension received */
+ OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
+ s->s3->tmp.peer_cert_sigalgs = NULL;
s->s3->tmp.peer_cert_sigalgslen = 0;
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_SRP
-static int init_srp(SSL *s, unsigned int context)
-{
- OPENSSL_free(s->srp_ctx.login);
- s->srp_ctx.login = NULL;
-
- return 1;
-}
-#endif
-
-static int init_etm(SSL *s, unsigned int context)
-{
- s->ext.use_etm = 0;
-
- return 1;
-}
-
-static int init_ems(SSL *s, unsigned int context)
-{
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRP
+static int init_srp(SSL *s, unsigned int context)
+{
+ OPENSSL_free(s->srp_ctx.login);
+ s->srp_ctx.login = NULL;
+
+ return 1;
+}
+#endif
+
+static int init_etm(SSL *s, unsigned int context)
+{
+ s->ext.use_etm = 0;
+
+ return 1;
+}
+
+static int init_ems(SSL *s, unsigned int context)
+{
if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
- s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+ s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
s->s3->flags |= TLS1_FLAGS_REQUIRED_EXTMS;
}
-
- return 1;
-}
-
-static int final_ems(SSL *s, unsigned int context, int sent)
-{
+
+ return 1;
+}
+
+static int final_ems(SSL *s, unsigned int context, int sent)
+{
/*
* Check extended master secret extension is not dropped on
* renegotiation.
@@ -1204,531 +1204,531 @@ static int final_ems(SSL *s, unsigned int context, int sent)
SSL_R_INCONSISTENT_EXTMS);
return 0;
}
- if (!s->server && s->hit) {
- /*
- * Check extended master secret extension is consistent with
- * original session.
- */
- if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
- !(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
- SSL_R_INCONSISTENT_EXTMS);
- return 0;
- }
- }
-
- return 1;
-}
-
-static int init_certificate_authorities(SSL *s, unsigned int context)
-{
- sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
- s->s3->tmp.peer_ca_names = NULL;
- return 1;
-}
-
-static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
- unsigned int context,
- X509 *x,
- size_t chainidx)
-{
- const STACK_OF(X509_NAME) *ca_sk = get_ca_names(s);
-
- if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- if (!construct_ca_names(s, ca_sk, pkt)) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
- }
-
- if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (!parse_ca_names(s, pkt))
- return 0;
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION);
- return 0;
- }
- return 1;
-}
-
-#ifndef OPENSSL_NO_SRTP
-static int init_srtp(SSL *s, unsigned int context)
-{
- if (s->server)
- s->srtp_profile = NULL;
-
- return 1;
-}
-#endif
-
-static int final_sig_algs(SSL *s, unsigned int context, int sent)
-{
- if (!sent && SSL_IS_TLS13(s) && !s->hit) {
- SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS,
- SSL_R_MISSING_SIGALGS_EXTENSION);
- return 0;
- }
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_EC
-static int final_key_share(SSL *s, unsigned int context, int sent)
-{
- if (!SSL_IS_TLS13(s))
- return 1;
-
- /* Nothing to do for key_share in an HRR */
- if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
- return 1;
-
- /*
- * If
- * we are a client
- * AND
- * we have no key_share
- * AND
- * (we are not resuming
- * OR the kex_mode doesn't allow non key_share resumes)
- * THEN
- * fail;
- */
- if (!s->server
- && !sent
- && (!s->hit
- || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
- /* Nothing left we can do - just fail */
- SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE,
- SSL_R_NO_SUITABLE_KEY_SHARE);
- return 0;
- }
- /*
- * IF
- * we are a server
- * THEN
- * IF
- * we have a suitable key_share
- * THEN
- * IF
- * we are stateless AND we have no cookie
- * THEN
- * send a HelloRetryRequest
- * ELSE
- * IF
- * we didn't already send a HelloRetryRequest
- * AND
- * the client sent a key_share extension
- * AND
- * (we are not resuming
- * OR the kex_mode allows key_share resumes)
- * AND
- * a shared group exists
- * THEN
- * send a HelloRetryRequest
- * ELSE IF
- * we are not resuming
- * OR
- * the kex_mode doesn't allow non key_share resumes
- * THEN
- * fail
- * ELSE IF
- * we are stateless AND we have no cookie
- * THEN
- * send a HelloRetryRequest
- */
- if (s->server) {
- if (s->s3->peer_tmp != NULL) {
- /* We have a suitable key_share */
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
- && !s->ext.cookieok) {
- if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
- /*
- * If we are stateless then we wouldn't know about any
- * previously sent HRR - so how can this be anything other
- * than 0?
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->hello_retry_request = SSL_HRR_PENDING;
- return 1;
- }
- } else {
- /* No suitable key_share */
- if (s->hello_retry_request == SSL_HRR_NONE && sent
- && (!s->hit
- || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE)
- != 0)) {
- const uint16_t *pgroups, *clntgroups;
- size_t num_groups, clnt_num_groups, i;
- unsigned int group_id = 0;
-
- /* Check if a shared group exists */
-
- /* Get the clients list of supported groups. */
- tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
- tls1_get_supported_groups(s, &pgroups, &num_groups);
-
- /*
- * Find the first group we allow that is also in client's list
- */
- for (i = 0; i < num_groups; i++) {
- group_id = pgroups[i];
-
- if (check_in_list(s, group_id, clntgroups, clnt_num_groups,
- 1))
- break;
- }
-
- if (i < num_groups) {
- /* A shared group exists so send a HelloRetryRequest */
- s->s3->group_id = group_id;
- s->hello_retry_request = SSL_HRR_PENDING;
- return 1;
- }
- }
- if (!s->hit
- || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) {
- /* Nothing left we can do - just fail */
- SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE
- : SSL_AD_MISSING_EXTENSION,
- SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
- return 0;
- }
-
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
- && !s->ext.cookieok) {
- if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
- /*
- * If we are stateless then we wouldn't know about any
- * previously sent HRR - so how can this be anything other
- * than 0?
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->hello_retry_request = SSL_HRR_PENDING;
- return 1;
- }
- }
-
- /*
- * We have a key_share so don't send any more HelloRetryRequest
- * messages
- */
- if (s->hello_retry_request == SSL_HRR_PENDING)
- s->hello_retry_request = SSL_HRR_COMPLETE;
- } else {
- /*
- * For a client side resumption with no key_share we need to generate
- * the handshake secret (otherwise this is done during key_share
- * processing).
- */
- if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- return 1;
-}
-#endif
-
-static int init_psk_kex_modes(SSL *s, unsigned int context)
-{
- s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
- return 1;
-}
-
-int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
- size_t binderoffset, const unsigned char *binderin,
- unsigned char *binderout, SSL_SESSION *sess, int sign,
- int external)
-{
- EVP_PKEY *mackey = NULL;
- EVP_MD_CTX *mctx = NULL;
- unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
- unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
- unsigned char *early_secret;
+ if (!s->server && s->hit) {
+ /*
+ * Check extended master secret extension is consistent with
+ * original session.
+ */
+ if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
+ !(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
+ SSL_R_INCONSISTENT_EXTMS);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int init_certificate_authorities(SSL *s, unsigned int context)
+{
+ sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
+ s->s3->tmp.peer_ca_names = NULL;
+ return 1;
+}
+
+static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
+ unsigned int context,
+ X509 *x,
+ size_t chainidx)
+{
+ const STACK_OF(X509_NAME) *ca_sk = get_ca_names(s);
+
+ if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities)
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!construct_ca_names(s, ca_sk, pkt)) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (!parse_ca_names(s, pkt))
+ return 0;
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRTP
+static int init_srtp(SSL *s, unsigned int context)
+{
+ if (s->server)
+ s->srtp_profile = NULL;
+
+ return 1;
+}
+#endif
+
+static int final_sig_algs(SSL *s, unsigned int context, int sent)
+{
+ if (!sent && SSL_IS_TLS13(s) && !s->hit) {
+ SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS,
+ SSL_R_MISSING_SIGALGS_EXTENSION);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+static int final_key_share(SSL *s, unsigned int context, int sent)
+{
+ if (!SSL_IS_TLS13(s))
+ return 1;
+
+ /* Nothing to do for key_share in an HRR */
+ if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
+ return 1;
+
+ /*
+ * If
+ * we are a client
+ * AND
+ * we have no key_share
+ * AND
+ * (we are not resuming
+ * OR the kex_mode doesn't allow non key_share resumes)
+ * THEN
+ * fail;
+ */
+ if (!s->server
+ && !sent
+ && (!s->hit
+ || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
+ /* Nothing left we can do - just fail */
+ SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE,
+ SSL_R_NO_SUITABLE_KEY_SHARE);
+ return 0;
+ }
+ /*
+ * IF
+ * we are a server
+ * THEN
+ * IF
+ * we have a suitable key_share
+ * THEN
+ * IF
+ * we are stateless AND we have no cookie
+ * THEN
+ * send a HelloRetryRequest
+ * ELSE
+ * IF
+ * we didn't already send a HelloRetryRequest
+ * AND
+ * the client sent a key_share extension
+ * AND
+ * (we are not resuming
+ * OR the kex_mode allows key_share resumes)
+ * AND
+ * a shared group exists
+ * THEN
+ * send a HelloRetryRequest
+ * ELSE IF
+ * we are not resuming
+ * OR
+ * the kex_mode doesn't allow non key_share resumes
+ * THEN
+ * fail
+ * ELSE IF
+ * we are stateless AND we have no cookie
+ * THEN
+ * send a HelloRetryRequest
+ */
+ if (s->server) {
+ if (s->s3->peer_tmp != NULL) {
+ /* We have a suitable key_share */
+ if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
+ && !s->ext.cookieok) {
+ if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
+ /*
+ * If we are stateless then we wouldn't know about any
+ * previously sent HRR - so how can this be anything other
+ * than 0?
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->hello_retry_request = SSL_HRR_PENDING;
+ return 1;
+ }
+ } else {
+ /* No suitable key_share */
+ if (s->hello_retry_request == SSL_HRR_NONE && sent
+ && (!s->hit
+ || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE)
+ != 0)) {
+ const uint16_t *pgroups, *clntgroups;
+ size_t num_groups, clnt_num_groups, i;
+ unsigned int group_id = 0;
+
+ /* Check if a shared group exists */
+
+ /* Get the clients list of supported groups. */
+ tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
+ tls1_get_supported_groups(s, &pgroups, &num_groups);
+
+ /*
+ * Find the first group we allow that is also in client's list
+ */
+ for (i = 0; i < num_groups; i++) {
+ group_id = pgroups[i];
+
+ if (check_in_list(s, group_id, clntgroups, clnt_num_groups,
+ 1))
+ break;
+ }
+
+ if (i < num_groups) {
+ /* A shared group exists so send a HelloRetryRequest */
+ s->s3->group_id = group_id;
+ s->hello_retry_request = SSL_HRR_PENDING;
+ return 1;
+ }
+ }
+ if (!s->hit
+ || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) {
+ /* Nothing left we can do - just fail */
+ SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE
+ : SSL_AD_MISSING_EXTENSION,
+ SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+ return 0;
+ }
+
+ if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
+ && !s->ext.cookieok) {
+ if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
+ /*
+ * If we are stateless then we wouldn't know about any
+ * previously sent HRR - so how can this be anything other
+ * than 0?
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->hello_retry_request = SSL_HRR_PENDING;
+ return 1;
+ }
+ }
+
+ /*
+ * We have a key_share so don't send any more HelloRetryRequest
+ * messages
+ */
+ if (s->hello_retry_request == SSL_HRR_PENDING)
+ s->hello_retry_request = SSL_HRR_COMPLETE;
+ } else {
+ /*
+ * For a client side resumption with no key_share we need to generate
+ * the handshake secret (otherwise this is done during key_share
+ * processing).
+ */
+ if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+static int init_psk_kex_modes(SSL *s, unsigned int context)
+{
+ s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
+ return 1;
+}
+
+int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
+ size_t binderoffset, const unsigned char *binderin,
+ unsigned char *binderout, SSL_SESSION *sess, int sign,
+ int external)
+{
+ EVP_PKEY *mackey = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
+ unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
+ unsigned char *early_secret;
#ifdef CHARSET_EBCDIC
static const unsigned char resumption_label[] = { 0x72, 0x65, 0x73, 0x20, 0x62, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x00 };
static const unsigned char external_label[] = { 0x65, 0x78, 0x74, 0x20, 0x62, 0x69, 0x6E, 0x64, 0x65, 0x72, 0x00 };
#else
- static const unsigned char resumption_label[] = "res binder";
- static const unsigned char external_label[] = "ext binder";
+ static const unsigned char resumption_label[] = "res binder";
+ static const unsigned char external_label[] = "ext binder";
#endif
- const unsigned char *label;
- size_t bindersize, labelsize, hashsize;
- int hashsizei = EVP_MD_size(md);
- int ret = -1;
- int usepskfored = 0;
-
- /* Ensure cast to size_t is safe */
- if (!ossl_assert(hashsizei >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- hashsize = (size_t)hashsizei;
-
- if (external
- && s->early_data_state == SSL_EARLY_DATA_CONNECTING
- && s->session->ext.max_early_data == 0
- && sess->ext.max_early_data > 0)
- usepskfored = 1;
-
- if (external) {
- label = external_label;
- labelsize = sizeof(external_label) - 1;
- } else {
- label = resumption_label;
- labelsize = sizeof(resumption_label) - 1;
- }
-
- /*
- * Generate the early_secret. On the server side we've selected a PSK to
- * resume with (internal or external) so we always do this. On the client
- * side we do this for a non-external (i.e. resumption) PSK or external PSK
- * that will be used for early_data so that it is in place for sending early
- * data. For client side external PSK not being used for early_data we
- * generate it but store it away for later use.
- */
- if (s->server || !external || usepskfored)
- early_secret = (unsigned char *)s->early_secret;
- else
- early_secret = (unsigned char *)sess->early_secret;
-
- if (!tls13_generate_secret(s, md, NULL, sess->master_key,
- sess->master_key_length, early_secret)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /*
- * Create the handshake hash for the binder key...the messages so far are
- * empty!
- */
- mctx = EVP_MD_CTX_new();
- if (mctx == NULL
- || EVP_DigestInit_ex(mctx, md, NULL) <= 0
- || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Generate the binder key */
- if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash,
- hashsize, binderkey, hashsize, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /* Generate the finished key */
- if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * Get a hash of the ClientHello up to the start of the binders. If we are
- * following a HelloRetryRequest then this includes the hash of the first
- * ClientHello and the HelloRetryRequest itself.
- */
- if (s->hello_retry_request == SSL_HRR_PENDING) {
- size_t hdatalen;
- long hdatalen_l;
- void *hdata;
-
- hdatalen = hdatalen_l =
- BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
- if (hdatalen_l <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- SSL_R_BAD_HANDSHAKE_LENGTH);
- goto err;
- }
-
- /*
- * For servers the handshake buffer data will include the second
- * ClientHello - which we don't want - so we need to take that bit off.
- */
- if (s->server) {
- PACKET hashprefix, msg;
-
- /* Find how many bytes are left after the first two messages */
- if (!PACKET_buf_init(&hashprefix, hdata, hdatalen)
- || !PACKET_forward(&hashprefix, 1)
- || !PACKET_get_length_prefixed_3(&hashprefix, &msg)
- || !PACKET_forward(&hashprefix, 1)
- || !PACKET_get_length_prefixed_3(&hashprefix, &msg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- hdatalen -= PACKET_remaining(&hashprefix);
- }
-
- if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
- if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
- || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- mackey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finishedkey,
- hashsize);
- if (mackey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (!sign)
- binderout = tmpbinder;
-
- bindersize = hashsize;
- if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
- || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
- || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
- || bindersize != hashsize) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (sign) {
- ret = 1;
- } else {
- /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
- ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
- if (!ret)
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER,
- SSL_R_BINDER_DOES_NOT_VERIFY);
- }
-
- err:
- OPENSSL_cleanse(binderkey, sizeof(binderkey));
- OPENSSL_cleanse(finishedkey, sizeof(finishedkey));
- EVP_PKEY_free(mackey);
- EVP_MD_CTX_free(mctx);
-
- return ret;
-}
-
-static int final_early_data(SSL *s, unsigned int context, int sent)
-{
- if (!sent)
- return 1;
-
- if (!s->server) {
- if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
- && sent
- && !s->ext.early_data_ok) {
- /*
- * If we get here then the server accepted our early_data but we
- * later realised that it shouldn't have done (e.g. inconsistent
- * ALPN)
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA,
- SSL_R_BAD_EARLY_DATA);
- return 0;
- }
-
- return 1;
- }
-
- if (s->max_early_data == 0
- || !s->hit
- || s->early_data_state != SSL_EARLY_DATA_ACCEPTING
- || !s->ext.early_data_ok
- || s->hello_retry_request != SSL_HRR_NONE
+ const unsigned char *label;
+ size_t bindersize, labelsize, hashsize;
+ int hashsizei = EVP_MD_size(md);
+ int ret = -1;
+ int usepskfored = 0;
+
+ /* Ensure cast to size_t is safe */
+ if (!ossl_assert(hashsizei >= 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hashsize = (size_t)hashsizei;
+
+ if (external
+ && s->early_data_state == SSL_EARLY_DATA_CONNECTING
+ && s->session->ext.max_early_data == 0
+ && sess->ext.max_early_data > 0)
+ usepskfored = 1;
+
+ if (external) {
+ label = external_label;
+ labelsize = sizeof(external_label) - 1;
+ } else {
+ label = resumption_label;
+ labelsize = sizeof(resumption_label) - 1;
+ }
+
+ /*
+ * Generate the early_secret. On the server side we've selected a PSK to
+ * resume with (internal or external) so we always do this. On the client
+ * side we do this for a non-external (i.e. resumption) PSK or external PSK
+ * that will be used for early_data so that it is in place for sending early
+ * data. For client side external PSK not being used for early_data we
+ * generate it but store it away for later use.
+ */
+ if (s->server || !external || usepskfored)
+ early_secret = (unsigned char *)s->early_secret;
+ else
+ early_secret = (unsigned char *)sess->early_secret;
+
+ if (!tls13_generate_secret(s, md, NULL, sess->master_key,
+ sess->master_key_length, early_secret)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /*
+ * Create the handshake hash for the binder key...the messages so far are
+ * empty!
+ */
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL
+ || EVP_DigestInit_ex(mctx, md, NULL) <= 0
+ || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Generate the binder key */
+ if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash,
+ hashsize, binderkey, hashsize, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /* Generate the finished key */
+ if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Get a hash of the ClientHello up to the start of the binders. If we are
+ * following a HelloRetryRequest then this includes the hash of the first
+ * ClientHello and the HelloRetryRequest itself.
+ */
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
+ size_t hdatalen;
+ long hdatalen_l;
+ void *hdata;
+
+ hdatalen = hdatalen_l =
+ BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (hdatalen_l <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ SSL_R_BAD_HANDSHAKE_LENGTH);
+ goto err;
+ }
+
+ /*
+ * For servers the handshake buffer data will include the second
+ * ClientHello - which we don't want - so we need to take that bit off.
+ */
+ if (s->server) {
+ PACKET hashprefix, msg;
+
+ /* Find how many bytes are left after the first two messages */
+ if (!PACKET_buf_init(&hashprefix, hdata, hdatalen)
+ || !PACKET_forward(&hashprefix, 1)
+ || !PACKET_get_length_prefixed_3(&hashprefix, &msg)
+ || !PACKET_forward(&hashprefix, 1)
+ || !PACKET_get_length_prefixed_3(&hashprefix, &msg)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hdatalen -= PACKET_remaining(&hashprefix);
+ }
+
+ if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
+ || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ mackey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finishedkey,
+ hashsize);
+ if (mackey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!sign)
+ binderout = tmpbinder;
+
+ bindersize = hashsize;
+ if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
+ || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
+ || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
+ || bindersize != hashsize) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (sign) {
+ ret = 1;
+ } else {
+ /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
+ ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
+ if (!ret)
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER,
+ SSL_R_BINDER_DOES_NOT_VERIFY);
+ }
+
+ err:
+ OPENSSL_cleanse(binderkey, sizeof(binderkey));
+ OPENSSL_cleanse(finishedkey, sizeof(finishedkey));
+ EVP_PKEY_free(mackey);
+ EVP_MD_CTX_free(mctx);
+
+ return ret;
+}
+
+static int final_early_data(SSL *s, unsigned int context, int sent)
+{
+ if (!sent)
+ return 1;
+
+ if (!s->server) {
+ if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+ && sent
+ && !s->ext.early_data_ok) {
+ /*
+ * If we get here then the server accepted our early_data but we
+ * later realised that it shouldn't have done (e.g. inconsistent
+ * ALPN)
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA,
+ SSL_R_BAD_EARLY_DATA);
+ return 0;
+ }
+
+ return 1;
+ }
+
+ if (s->max_early_data == 0
+ || !s->hit
+ || s->early_data_state != SSL_EARLY_DATA_ACCEPTING
+ || !s->ext.early_data_ok
+ || s->hello_retry_request != SSL_HRR_NONE
|| (s->allow_early_data_cb != NULL
&& !s->allow_early_data_cb(s,
s->allow_early_data_cb_data))) {
- s->ext.early_data = SSL_EARLY_DATA_REJECTED;
- } else {
- s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
-
- if (!tls13_change_cipher_state(s,
- SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
-
- return 1;
-}
-
-static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
-{
- /*
- * Session resumption on server-side with MFL extension active
- * BUT MFL extension packet was not resent (i.e. sent == 0)
- */
- if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
- && !sent ) {
- SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- /* Current SSL buffer is lower than requested MFL */
- if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
- && s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session))
- /* trigger a larger buffer reallocation */
- if (!ssl3_setup_buffers(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-static int init_post_handshake_auth(SSL *s, unsigned int context)
-{
- s->post_handshake_auth = SSL_PHA_NONE;
-
- return 1;
-}
+ s->ext.early_data = SSL_EARLY_DATA_REJECTED;
+ } else {
+ s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
+
+ if (!tls13_change_cipher_state(s,
+ SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
+{
+ /*
+ * Session resumption on server-side with MFL extension active
+ * BUT MFL extension packet was not resent (i.e. sent == 0)
+ */
+ if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
+ && !sent ) {
+ SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ /* Current SSL buffer is lower than requested MFL */
+ if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
+ && s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session))
+ /* trigger a larger buffer reallocation */
+ if (!ssl3_setup_buffers(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+static int init_post_handshake_auth(SSL *s, unsigned int context)
+{
+ s->post_handshake_auth = SSL_PHA_NONE;
+
+ return 1;
+}
/*
* If clients offer "pre_shared_key" without a "psk_key_exchange_modes"
diff --git a/contrib/libs/openssl/ssl/statem/extensions_clnt.c b/contrib/libs/openssl/ssl/statem/extensions_clnt.c
index ce8a75794c..2da1070bce 100644
--- a/contrib/libs/openssl/ssl/statem/extensions_clnt.c
+++ b/contrib/libs/openssl/ssl/statem/extensions_clnt.c
@@ -1,1967 +1,1967 @@
-/*
+/*
* Copyright 2016-2021 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 <openssl/ocsp.h>
+ *
+ * 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 <openssl/ocsp.h>
#include "../ssl_local.h"
-#include "internal/cryptlib.h"
+#include "internal/cryptlib.h"
#include "statem_local.h"
-
-EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- /* Add RI if renegotiating */
- if (!s->renegotiate)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (s->ext.hostname == NULL)
- return EXT_RETURN_NOT_SENT;
-
- /* Add TLS extension servername to the Client Hello message */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
- /* Sub-packet for server_name extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* Sub-packet for servername list (always 1 hostname)*/
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name)
- || !WPACKET_sub_memcpy_u16(pkt, s->ext.hostname,
- strlen(s->ext.hostname))
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-/* Push a Max Fragment Len extension into ClientHello */
-EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED)
- return EXT_RETURN_NOT_SENT;
-
- /* Add Max Fragment Length extension if client enabled it. */
- /*-
- * 4 bytes for this extension type and extension length
- * 1 byte for the Max Fragment Length code value.
- */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
- /* Sub-packet for Max Fragment Length extension (1 byte) */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-#ifndef OPENSSL_NO_SRP
-EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- /* Add SRP username if there is one */
- if (s->srp_ctx.login == NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp)
- /* Sub-packet for SRP extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)
- /* login must not be zero...internal error if so */
- || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
- || !WPACKET_memcpy(pkt, s->srp_ctx.login,
- strlen(s->srp_ctx.login))
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SRP,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-#ifndef OPENSSL_NO_EC
-static int use_ecc(SSL *s)
-{
- int i, end, ret = 0;
- unsigned long alg_k, alg_a;
- STACK_OF(SSL_CIPHER) *cipher_stack = NULL;
-
- /* See if we support any ECC ciphersuites */
- if (s->version == SSL3_VERSION)
- return 0;
-
- cipher_stack = SSL_get1_supported_ciphers(s);
- end = sk_SSL_CIPHER_num(cipher_stack);
- for (i = 0; i < end; i++) {
- const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
-
- alg_k = c->algorithm_mkey;
- alg_a = c->algorithm_auth;
- if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
- || (alg_a & SSL_aECDSA)
- || c->min_tls >= TLS1_3_VERSION) {
- ret = 1;
- break;
- }
- }
-
- sk_SSL_CIPHER_free(cipher_stack);
- return ret;
-}
-
-EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- const unsigned char *pformats;
- size_t num_formats;
-
- if (!use_ecc(s))
- return EXT_RETURN_NOT_SENT;
-
- /* Add TLS extension ECPointFormats to the ClientHello message */
- tls1_get_formatlist(s, &pformats, &num_formats);
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
- /* Sub-packet for formats extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- const uint16_t *pgroups = NULL;
- size_t num_groups = 0, i;
-
- if (!use_ecc(s))
- return EXT_RETURN_NOT_SENT;
-
- /*
- * Add TLS extension supported_groups to the ClientHello message
- */
- /* TODO(TLS1.3): Add support for DHE groups */
- tls1_get_supported_groups(s, &pgroups, &num_groups);
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
- /* Sub-packet for supported_groups extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- /* Copy curve ID if supported */
- for (i = 0; i < num_groups; i++) {
- uint16_t ctmp = pgroups[i];
-
- if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
- if (!WPACKET_put_bytes_u16(pkt, ctmp)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- size_t ticklen;
-
- if (!tls_use_ticket(s))
- return EXT_RETURN_NOT_SENT;
-
- if (!s->new_session && s->session != NULL
- && s->session->ext.tick != NULL
- && s->session->ssl_version != TLS1_3_VERSION) {
- ticklen = s->session->ext.ticklen;
- } else if (s->session && s->ext.session_ticket != NULL
- && s->ext.session_ticket->data != NULL) {
- ticklen = s->ext.session_ticket->length;
- s->session->ext.tick = OPENSSL_malloc(ticklen);
- if (s->session->ext.tick == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- memcpy(s->session->ext.tick,
- s->ext.session_ticket->data, ticklen);
- s->session->ext.ticklen = ticklen;
- } else {
- ticklen = 0;
- }
-
- if (ticklen == 0 && s->ext.session_ticket != NULL &&
- s->ext.session_ticket->data == NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
- || !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- size_t salglen;
- const uint16_t *salg;
-
- if (!SSL_CLIENT_USE_SIGALGS(s))
- return EXT_RETURN_NOT_SENT;
-
- salglen = tls12_get_psigalgs(s, 1, &salg);
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms)
- /* Sub-packet for sig-algs extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* Sub-packet for the actual list */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !tls12_copy_sigalgs(s, pkt, salg, salglen)
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-#ifndef OPENSSL_NO_OCSP
-EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- int i;
-
- /* This extension isn't defined for client Certificates */
- if (x != NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
- /* Sub-packet for status request extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
- /* Sub-packet for the ids */
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) {
- unsigned char *idbytes;
- OCSP_RESPID *id = sk_OCSP_RESPID_value(s->ext.ocsp.ids, i);
- int idlen = i2d_OCSP_RESPID(id, NULL);
-
- if (idlen <= 0
- /* Sub-packet for an individual id */
- || !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
- || i2d_OCSP_RESPID(id, &idbytes) != idlen) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- }
- if (!WPACKET_close(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- if (s->ext.ocsp.exts) {
- unsigned char *extbytes;
- int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL);
-
- if (extlen < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
- || i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes)
- != extlen) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
-EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
- return EXT_RETURN_NOT_SENT;
-
- /*
- * The client advertises an empty extension to indicate its support
- * for Next Protocol Negotiation
- */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- s->s3->alpn_sent = 0;
-
- if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt,
- TLSEXT_TYPE_application_layer_protocol_negotiation)
- /* Sub-packet ALPN extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- s->s3->alpn_sent = 1;
-
- return EXT_RETURN_SENT;
-}
-
-
-#ifndef OPENSSL_NO_SRTP
-EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
- int i, end;
-
- if (clnt == NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
- /* Sub-packet for SRTP extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* Sub-packet for the protection profile list */
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- end = sk_SRTP_PROTECTION_PROFILE_num(clnt);
- for (i = 0; i < end; i++) {
- const SRTP_PROTECTION_PROFILE *prof =
- sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
-
- if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- }
- if (!WPACKET_close(pkt)
- /* Add an empty use_mki value */
- || !WPACKET_put_bytes_u8(pkt, 0)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-#ifndef OPENSSL_NO_CT
-EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (s->ct_validation_callback == NULL)
- return EXT_RETURN_NOT_SENT;
-
- /* Not defined for client Certificates */
- if (x != NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- int currv, min_version, max_version, reason;
-
- reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
- if (reason != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
- return EXT_RETURN_FAIL;
- }
-
- /*
- * Don't include this if we can't negotiate TLSv1.3. We can do a straight
- * comparison here because we will never be called in DTLS.
- */
- if (max_version < TLS1_3_VERSION)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- for (currv = max_version; currv >= min_version; currv--) {
- if (!WPACKET_put_bytes_u16(pkt, currv)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-/*
- * Construct a psk_kex_modes extension.
- */
-EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)
- || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE)
- || (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE))
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE_DHE;
- if (nodhe)
- s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
-#endif
-
- return EXT_RETURN_SENT;
-}
-
-#ifndef OPENSSL_NO_TLS1_3
-static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
-{
- unsigned char *encoded_point = NULL;
- EVP_PKEY *key_share_key = NULL;
- size_t encodedlen;
-
- if (s->s3->tmp.pkey != NULL) {
- if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- /*
- * Could happen if we got an HRR that wasn't requesting a new key_share
- */
- key_share_key = s->s3->tmp.pkey;
- } else {
- key_share_key = ssl_generate_pkey_group(s, curve_id);
- if (key_share_key == NULL) {
- /* SSLfatal() already called */
- return 0;
- }
- }
-
- /* Encode the public key. */
- encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
- &encoded_point);
- if (encodedlen == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB);
- goto err;
- }
-
- /* Create KeyShareEntry */
- if (!WPACKET_put_bytes_u16(pkt, curve_id)
- || !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * TODO(TLS1.3): When changing to send more than one key_share we're
- * going to need to be able to save more than one EVP_PKEY. For now
- * we reuse the existing tmp.pkey
- */
- s->s3->tmp.pkey = key_share_key;
- s->s3->group_id = curve_id;
- OPENSSL_free(encoded_point);
-
- return 1;
- err:
- if (s->s3->tmp.pkey == NULL)
- EVP_PKEY_free(key_share_key);
- OPENSSL_free(encoded_point);
- return 0;
-}
-#endif
-
-EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- size_t i, num_groups = 0;
- const uint16_t *pgroups = NULL;
- uint16_t curve_id = 0;
-
- /* key_share extension */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
- /* Extension data sub-packet */
- || !WPACKET_start_sub_packet_u16(pkt)
- /* KeyShare list sub-packet */
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- tls1_get_supported_groups(s, &pgroups, &num_groups);
-
- /*
- * TODO(TLS1.3): Make the number of key_shares sent configurable. For
- * now, just send one
- */
- if (s->s3->group_id != 0) {
- curve_id = s->s3->group_id;
- } else {
- for (i = 0; i < num_groups; i++) {
-
- if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED))
- continue;
-
- curve_id = pgroups[i];
- break;
- }
- }
-
- if (curve_id == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
- SSL_R_NO_SUITABLE_KEY_SHARE);
- return EXT_RETURN_FAIL;
- }
-
- if (!add_key_share(s, pkt, curve_id)) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
- }
-
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- return EXT_RETURN_SENT;
-#else
- return EXT_RETURN_NOT_SENT;
-#endif
-}
-
-EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- EXT_RETURN ret = EXT_RETURN_FAIL;
-
- /* Should only be set if we've had an HRR */
- if (s->ext.tls13_cookie_len == 0)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
- /* Extension data sub-packet */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie,
- s->ext.tls13_cookie_len)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
-
- ret = EXT_RETURN_SENT;
- end:
- OPENSSL_free(s->ext.tls13_cookie);
- s->ext.tls13_cookie = NULL;
- s->ext.tls13_cookie_len = 0;
-
- return ret;
-}
-
-EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_PSK
- char identity[PSK_MAX_IDENTITY_LEN + 1];
-#endif /* OPENSSL_NO_PSK */
- const unsigned char *id = NULL;
- size_t idlen = 0;
- SSL_SESSION *psksess = NULL;
- SSL_SESSION *edsess = NULL;
- const EVP_MD *handmd = NULL;
-
- if (s->hello_retry_request == SSL_HRR_PENDING)
- handmd = ssl_handshake_md(s);
-
- if (s->psk_use_session_cb != NULL
- && (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)
- || (psksess != NULL
- && psksess->ssl_version != TLS1_3_VERSION))) {
- SSL_SESSION_free(psksess);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- SSL_R_BAD_PSK);
- return EXT_RETURN_FAIL;
- }
-
-#ifndef OPENSSL_NO_PSK
- if (psksess == NULL && s->psk_client_callback != NULL) {
- unsigned char psk[PSK_MAX_PSK_LEN];
- size_t psklen = 0;
-
- memset(identity, 0, sizeof(identity));
- psklen = s->psk_client_callback(s, NULL, identity, sizeof(identity) - 1,
- psk, sizeof(psk));
-
- if (psklen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- } else if (psklen > 0) {
- const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
- const SSL_CIPHER *cipher;
-
- idlen = strlen(identity);
- if (idlen > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- id = (unsigned char *)identity;
-
- /*
- * We found a PSK using an old style callback. We don't know
- * the digest so we default to SHA256 as per the TLSv1.3 spec
- */
- cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
- if (cipher == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- psksess = SSL_SESSION_new();
- if (psksess == NULL
- || !SSL_SESSION_set1_master_key(psksess, psk, psklen)
- || !SSL_SESSION_set_cipher(psksess, cipher)
- || !SSL_SESSION_set_protocol_version(psksess, TLS1_3_VERSION)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
- OPENSSL_cleanse(psk, psklen);
- return EXT_RETURN_FAIL;
- }
- OPENSSL_cleanse(psk, psklen);
- }
- }
-#endif /* OPENSSL_NO_PSK */
-
- SSL_SESSION_free(s->psksession);
- s->psksession = psksess;
- if (psksess != NULL) {
- OPENSSL_free(s->psksession_id);
- s->psksession_id = OPENSSL_memdup(id, idlen);
- if (s->psksession_id == NULL) {
+
+EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ /* Add RI if renegotiating */
+ if (!s->renegotiate)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (s->ext.hostname == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ /* Add TLS extension servername to the Client Hello message */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
+ /* Sub-packet for server_name extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ /* Sub-packet for servername list (always 1 hostname)*/
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name)
+ || !WPACKET_sub_memcpy_u16(pkt, s->ext.hostname,
+ strlen(s->ext.hostname))
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+/* Push a Max Fragment Len extension into ClientHello */
+EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED)
+ return EXT_RETURN_NOT_SENT;
+
+ /* Add Max Fragment Length extension if client enabled it. */
+ /*-
+ * 4 bytes for this extension type and extension length
+ * 1 byte for the Max Fragment Length code value.
+ */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
+ /* Sub-packet for Max Fragment Length extension (1 byte) */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+#ifndef OPENSSL_NO_SRP
+EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ /* Add SRP username if there is one */
+ if (s->srp_ctx.login == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp)
+ /* Sub-packet for SRP extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u8(pkt)
+ /* login must not be zero...internal error if so */
+ || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
+ || !WPACKET_memcpy(pkt, s->srp_ctx.login,
+ strlen(s->srp_ctx.login))
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SRP,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+static int use_ecc(SSL *s)
+{
+ int i, end, ret = 0;
+ unsigned long alg_k, alg_a;
+ STACK_OF(SSL_CIPHER) *cipher_stack = NULL;
+
+ /* See if we support any ECC ciphersuites */
+ if (s->version == SSL3_VERSION)
+ return 0;
+
+ cipher_stack = SSL_get1_supported_ciphers(s);
+ end = sk_SSL_CIPHER_num(cipher_stack);
+ for (i = 0; i < end; i++) {
+ const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
+
+ alg_k = c->algorithm_mkey;
+ alg_a = c->algorithm_auth;
+ if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
+ || (alg_a & SSL_aECDSA)
+ || c->min_tls >= TLS1_3_VERSION) {
+ ret = 1;
+ break;
+ }
+ }
+
+ sk_SSL_CIPHER_free(cipher_stack);
+ return ret;
+}
+
+EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ const unsigned char *pformats;
+ size_t num_formats;
+
+ if (!use_ecc(s))
+ return EXT_RETURN_NOT_SENT;
+
+ /* Add TLS extension ECPointFormats to the ClientHello message */
+ tls1_get_formatlist(s, &pformats, &num_formats);
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
+ /* Sub-packet for formats extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ const uint16_t *pgroups = NULL;
+ size_t num_groups = 0, i;
+
+ if (!use_ecc(s))
+ return EXT_RETURN_NOT_SENT;
+
+ /*
+ * Add TLS extension supported_groups to the ClientHello message
+ */
+ /* TODO(TLS1.3): Add support for DHE groups */
+ tls1_get_supported_groups(s, &pgroups, &num_groups);
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
+ /* Sub-packet for supported_groups extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ /* Copy curve ID if supported */
+ for (i = 0; i < num_groups; i++) {
+ uint16_t ctmp = pgroups[i];
+
+ if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
+ if (!WPACKET_put_bytes_u16(pkt, ctmp)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ size_t ticklen;
+
+ if (!tls_use_ticket(s))
+ return EXT_RETURN_NOT_SENT;
+
+ if (!s->new_session && s->session != NULL
+ && s->session->ext.tick != NULL
+ && s->session->ssl_version != TLS1_3_VERSION) {
+ ticklen = s->session->ext.ticklen;
+ } else if (s->session && s->ext.session_ticket != NULL
+ && s->ext.session_ticket->data != NULL) {
+ ticklen = s->ext.session_ticket->length;
+ s->session->ext.tick = OPENSSL_malloc(ticklen);
+ if (s->session->ext.tick == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ memcpy(s->session->ext.tick,
+ s->ext.session_ticket->data, ticklen);
+ s->session->ext.ticklen = ticklen;
+ } else {
+ ticklen = 0;
+ }
+
+ if (ticklen == 0 && s->ext.session_ticket != NULL &&
+ s->ext.session_ticket->data == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
+ || !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ size_t salglen;
+ const uint16_t *salg;
+
+ if (!SSL_CLIENT_USE_SIGALGS(s))
+ return EXT_RETURN_NOT_SENT;
+
+ salglen = tls12_get_psigalgs(s, 1, &salg);
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms)
+ /* Sub-packet for sig-algs extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ /* Sub-packet for the actual list */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !tls12_copy_sigalgs(s, pkt, salg, salglen)
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+#ifndef OPENSSL_NO_OCSP
+EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ int i;
+
+ /* This extension isn't defined for client Certificates */
+ if (x != NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
+ /* Sub-packet for status request extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
+ /* Sub-packet for the ids */
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) {
+ unsigned char *idbytes;
+ OCSP_RESPID *id = sk_OCSP_RESPID_value(s->ext.ocsp.ids, i);
+ int idlen = i2d_OCSP_RESPID(id, NULL);
+
+ if (idlen <= 0
+ /* Sub-packet for an individual id */
+ || !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
+ || i2d_OCSP_RESPID(id, &idbytes) != idlen) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ }
+ if (!WPACKET_close(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ if (s->ext.ocsp.exts) {
+ unsigned char *extbytes;
+ int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL);
+
+ if (extlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
+ || i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes)
+ != extlen) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
+ return EXT_RETURN_NOT_SENT;
+
+ /*
+ * The client advertises an empty extension to indicate its support
+ * for Next Protocol Negotiation
+ */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ s->s3->alpn_sent = 0;
+
+ if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt,
+ TLSEXT_TYPE_application_layer_protocol_negotiation)
+ /* Sub-packet ALPN extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ s->s3->alpn_sent = 1;
+
+ return EXT_RETURN_SENT;
+}
+
+
+#ifndef OPENSSL_NO_SRTP
+EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
+ int i, end;
+
+ if (clnt == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
+ /* Sub-packet for SRTP extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ /* Sub-packet for the protection profile list */
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ end = sk_SRTP_PROTECTION_PROFILE_num(clnt);
+ for (i = 0; i < end; i++) {
+ const SRTP_PROTECTION_PROFILE *prof =
+ sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
+
+ if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ }
+ if (!WPACKET_close(pkt)
+ /* Add an empty use_mki value */
+ || !WPACKET_put_bytes_u8(pkt, 0)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+#ifndef OPENSSL_NO_CT
+EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (s->ct_validation_callback == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ /* Not defined for client Certificates */
+ if (x != NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ int currv, min_version, max_version, reason;
+
+ reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
+ if (reason != 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * Don't include this if we can't negotiate TLSv1.3. We can do a straight
+ * comparison here because we will never be called in DTLS.
+ */
+ if (max_version < TLS1_3_VERSION)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u8(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ for (currv = max_version; currv >= min_version; currv--) {
+ if (!WPACKET_put_bytes_u16(pkt, currv)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+/*
+ * Construct a psk_kex_modes extension.
+ */
+EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u8(pkt)
+ || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE)
+ || (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE))
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE_DHE;
+ if (nodhe)
+ s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
+#endif
+
+ return EXT_RETURN_SENT;
+}
+
+#ifndef OPENSSL_NO_TLS1_3
+static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
+{
+ unsigned char *encoded_point = NULL;
+ EVP_PKEY *key_share_key = NULL;
+ size_t encodedlen;
+
+ if (s->s3->tmp.pkey != NULL) {
+ if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ /*
+ * Could happen if we got an HRR that wasn't requesting a new key_share
+ */
+ key_share_key = s->s3->tmp.pkey;
+ } else {
+ key_share_key = ssl_generate_pkey_group(s, curve_id);
+ if (key_share_key == NULL) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+
+ /* Encode the public key. */
+ encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
+ &encoded_point);
+ if (encodedlen == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* Create KeyShareEntry */
+ if (!WPACKET_put_bytes_u16(pkt, curve_id)
+ || !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * TODO(TLS1.3): When changing to send more than one key_share we're
+ * going to need to be able to save more than one EVP_PKEY. For now
+ * we reuse the existing tmp.pkey
+ */
+ s->s3->tmp.pkey = key_share_key;
+ s->s3->group_id = curve_id;
+ OPENSSL_free(encoded_point);
+
+ return 1;
+ err:
+ if (s->s3->tmp.pkey == NULL)
+ EVP_PKEY_free(key_share_key);
+ OPENSSL_free(encoded_point);
+ return 0;
+}
+#endif
+
+EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ size_t i, num_groups = 0;
+ const uint16_t *pgroups = NULL;
+ uint16_t curve_id = 0;
+
+ /* key_share extension */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
+ /* Extension data sub-packet */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ /* KeyShare list sub-packet */
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ tls1_get_supported_groups(s, &pgroups, &num_groups);
+
+ /*
+ * TODO(TLS1.3): Make the number of key_shares sent configurable. For
+ * now, just send one
+ */
+ if (s->s3->group_id != 0) {
+ curve_id = s->s3->group_id;
+ } else {
+ for (i = 0; i < num_groups; i++) {
+
+ if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED))
+ continue;
+
+ curve_id = pgroups[i];
+ break;
+ }
+ }
+
+ if (curve_id == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
+ SSL_R_NO_SUITABLE_KEY_SHARE);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!add_key_share(s, pkt, curve_id)) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ return EXT_RETURN_SENT;
+#else
+ return EXT_RETURN_NOT_SENT;
+#endif
+}
+
+EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ EXT_RETURN ret = EXT_RETURN_FAIL;
+
+ /* Should only be set if we've had an HRR */
+ if (s->ext.tls13_cookie_len == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
+ /* Extension data sub-packet */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie,
+ s->ext.tls13_cookie_len)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+
+ ret = EXT_RETURN_SENT;
+ end:
+ OPENSSL_free(s->ext.tls13_cookie);
+ s->ext.tls13_cookie = NULL;
+ s->ext.tls13_cookie_len = 0;
+
+ return ret;
+}
+
+EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_PSK
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+#endif /* OPENSSL_NO_PSK */
+ const unsigned char *id = NULL;
+ size_t idlen = 0;
+ SSL_SESSION *psksess = NULL;
+ SSL_SESSION *edsess = NULL;
+ const EVP_MD *handmd = NULL;
+
+ if (s->hello_retry_request == SSL_HRR_PENDING)
+ handmd = ssl_handshake_md(s);
+
+ if (s->psk_use_session_cb != NULL
+ && (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)
+ || (psksess != NULL
+ && psksess->ssl_version != TLS1_3_VERSION))) {
+ SSL_SESSION_free(psksess);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ SSL_R_BAD_PSK);
+ return EXT_RETURN_FAIL;
+ }
+
+#ifndef OPENSSL_NO_PSK
+ if (psksess == NULL && s->psk_client_callback != NULL) {
+ unsigned char psk[PSK_MAX_PSK_LEN];
+ size_t psklen = 0;
+
+ memset(identity, 0, sizeof(identity));
+ psklen = s->psk_client_callback(s, NULL, identity, sizeof(identity) - 1,
+ psk, sizeof(psk));
+
+ if (psklen > PSK_MAX_PSK_LEN) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ } else if (psklen > 0) {
+ const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
+ const SSL_CIPHER *cipher;
+
+ idlen = strlen(identity);
+ if (idlen > PSK_MAX_IDENTITY_LEN) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ id = (unsigned char *)identity;
+
+ /*
+ * We found a PSK using an old style callback. We don't know
+ * the digest so we default to SHA256 as per the TLSv1.3 spec
+ */
+ cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
+ if (cipher == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ psksess = SSL_SESSION_new();
+ if (psksess == NULL
+ || !SSL_SESSION_set1_master_key(psksess, psk, psklen)
+ || !SSL_SESSION_set_cipher(psksess, cipher)
+ || !SSL_SESSION_set_protocol_version(psksess, TLS1_3_VERSION)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ ERR_R_INTERNAL_ERROR);
+ OPENSSL_cleanse(psk, psklen);
+ return EXT_RETURN_FAIL;
+ }
+ OPENSSL_cleanse(psk, psklen);
+ }
+ }
+#endif /* OPENSSL_NO_PSK */
+
+ SSL_SESSION_free(s->psksession);
+ s->psksession = psksess;
+ if (psksess != NULL) {
+ OPENSSL_free(s->psksession_id);
+ s->psksession_id = OPENSSL_memdup(id, idlen);
+ if (s->psksession_id == NULL) {
s->psksession_id_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- s->psksession_id_len = idlen;
- }
-
- if (s->early_data_state != SSL_EARLY_DATA_CONNECTING
- || (s->session->ext.max_early_data == 0
- && (psksess == NULL || psksess->ext.max_early_data == 0))) {
- s->max_early_data = 0;
- return EXT_RETURN_NOT_SENT;
- }
- edsess = s->session->ext.max_early_data != 0 ? s->session : psksess;
- s->max_early_data = edsess->ext.max_early_data;
-
- if (edsess->ext.hostname != NULL) {
- if (s->ext.hostname == NULL
- || (s->ext.hostname != NULL
- && strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- SSL_R_INCONSISTENT_EARLY_DATA_SNI);
- return EXT_RETURN_FAIL;
- }
- }
-
- if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
- return EXT_RETURN_FAIL;
- }
-
- /*
- * Verify that we are offering an ALPN protocol consistent with the early
- * data.
- */
- if (edsess->ext.alpn_selected != NULL) {
- PACKET prots, alpnpkt;
- int found = 0;
-
- if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) {
- if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected,
- edsess->ext.alpn_selected_len)) {
- found = 1;
- break;
- }
- }
- if (!found) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
- return EXT_RETURN_FAIL;
- }
- }
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- /*
- * We set this to rejected here. Later, if the server acknowledges the
- * extension, we set it to accepted.
- */
- s->ext.early_data = SSL_EARLY_DATA_REJECTED;
- s->ext.early_data_ok = 1;
-
- return EXT_RETURN_SENT;
-}
-
-#define F5_WORKAROUND_MIN_MSG_LEN 0xff
-#define F5_WORKAROUND_MAX_MSG_LEN 0x200
-
-/*
- * PSK pre binder overhead =
- * 2 bytes for TLSEXT_TYPE_psk
- * 2 bytes for extension length
- * 2 bytes for identities list length
- * 2 bytes for identity length
- * 4 bytes for obfuscated_ticket_age
- * 2 bytes for binder list length
- * 1 byte for binder length
- * The above excludes the number of bytes for the identity itself and the
- * subsequent binder bytes
- */
-#define PSK_PRE_BINDER_OVERHEAD (2 + 2 + 2 + 2 + 4 + 2 + 1)
-
-EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- unsigned char *padbytes;
- size_t hlen;
-
- if ((s->options & SSL_OP_TLSEXT_PADDING) == 0)
- return EXT_RETURN_NOT_SENT;
-
- /*
- * Add padding to workaround bugs in F5 terminators. See RFC7685.
- * This code calculates the length of all extensions added so far but
- * excludes the PSK extension (because that MUST be written last). Therefore
- * this extension MUST always appear second to last.
- */
- if (!WPACKET_get_total_written(pkt, &hlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- /*
- * If we're going to send a PSK then that will be written out after this
- * extension, so we need to calculate how long it is going to be.
- */
- if (s->session->ssl_version == TLS1_3_VERSION
- && s->session->ext.ticklen != 0
- && s->session->cipher != NULL) {
- const EVP_MD *md = ssl_md(s->session->cipher->algorithm2);
-
- if (md != NULL) {
- /*
- * Add the fixed PSK overhead, the identity length and the binder
- * length.
- */
- hlen += PSK_PRE_BINDER_OVERHEAD + s->session->ext.ticklen
- + EVP_MD_size(md);
- }
- }
-
- if (hlen > F5_WORKAROUND_MIN_MSG_LEN && hlen < F5_WORKAROUND_MAX_MSG_LEN) {
- /* Calculate the amount of padding we need to add */
- hlen = F5_WORKAROUND_MAX_MSG_LEN - hlen;
-
- /*
- * Take off the size of extension header itself (2 bytes for type and
- * 2 bytes for length bytes), but ensure that the extension is at least
- * 1 byte long so as not to have an empty extension last (WebSphere 7.x,
- * 8.x are intolerant of that condition)
- */
- if (hlen > 4)
- hlen -= 4;
- else
- hlen = 1;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
- || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- memset(padbytes, 0, hlen);
- }
-
- return EXT_RETURN_SENT;
-}
-
-/*
- * Construct the pre_shared_key extension
- */
-EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- uint32_t now, agesec, agems = 0;
- size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen;
- unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL;
- const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL;
- int dores = 0;
-
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ s->psksession_id_len = idlen;
+ }
+
+ if (s->early_data_state != SSL_EARLY_DATA_CONNECTING
+ || (s->session->ext.max_early_data == 0
+ && (psksess == NULL || psksess->ext.max_early_data == 0))) {
+ s->max_early_data = 0;
+ return EXT_RETURN_NOT_SENT;
+ }
+ edsess = s->session->ext.max_early_data != 0 ? s->session : psksess;
+ s->max_early_data = edsess->ext.max_early_data;
+
+ if (edsess->ext.hostname != NULL) {
+ if (s->ext.hostname == NULL
+ || (s->ext.hostname != NULL
+ && strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ SSL_R_INCONSISTENT_EARLY_DATA_SNI);
+ return EXT_RETURN_FAIL;
+ }
+ }
+
+ if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * Verify that we are offering an ALPN protocol consistent with the early
+ * data.
+ */
+ if (edsess->ext.alpn_selected != NULL) {
+ PACKET prots, alpnpkt;
+ int found = 0;
+
+ if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) {
+ if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected,
+ edsess->ext.alpn_selected_len)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
+ return EXT_RETURN_FAIL;
+ }
+ }
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * We set this to rejected here. Later, if the server acknowledges the
+ * extension, we set it to accepted.
+ */
+ s->ext.early_data = SSL_EARLY_DATA_REJECTED;
+ s->ext.early_data_ok = 1;
+
+ return EXT_RETURN_SENT;
+}
+
+#define F5_WORKAROUND_MIN_MSG_LEN 0xff
+#define F5_WORKAROUND_MAX_MSG_LEN 0x200
+
+/*
+ * PSK pre binder overhead =
+ * 2 bytes for TLSEXT_TYPE_psk
+ * 2 bytes for extension length
+ * 2 bytes for identities list length
+ * 2 bytes for identity length
+ * 4 bytes for obfuscated_ticket_age
+ * 2 bytes for binder list length
+ * 1 byte for binder length
+ * The above excludes the number of bytes for the identity itself and the
+ * subsequent binder bytes
+ */
+#define PSK_PRE_BINDER_OVERHEAD (2 + 2 + 2 + 2 + 4 + 2 + 1)
+
+EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ unsigned char *padbytes;
+ size_t hlen;
+
+ if ((s->options & SSL_OP_TLSEXT_PADDING) == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ /*
+ * Add padding to workaround bugs in F5 terminators. See RFC7685.
+ * This code calculates the length of all extensions added so far but
+ * excludes the PSK extension (because that MUST be written last). Therefore
+ * this extension MUST always appear second to last.
+ */
+ if (!WPACKET_get_total_written(pkt, &hlen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * If we're going to send a PSK then that will be written out after this
+ * extension, so we need to calculate how long it is going to be.
+ */
+ if (s->session->ssl_version == TLS1_3_VERSION
+ && s->session->ext.ticklen != 0
+ && s->session->cipher != NULL) {
+ const EVP_MD *md = ssl_md(s->session->cipher->algorithm2);
+
+ if (md != NULL) {
+ /*
+ * Add the fixed PSK overhead, the identity length and the binder
+ * length.
+ */
+ hlen += PSK_PRE_BINDER_OVERHEAD + s->session->ext.ticklen
+ + EVP_MD_size(md);
+ }
+ }
+
+ if (hlen > F5_WORKAROUND_MIN_MSG_LEN && hlen < F5_WORKAROUND_MAX_MSG_LEN) {
+ /* Calculate the amount of padding we need to add */
+ hlen = F5_WORKAROUND_MAX_MSG_LEN - hlen;
+
+ /*
+ * Take off the size of extension header itself (2 bytes for type and
+ * 2 bytes for length bytes), but ensure that the extension is at least
+ * 1 byte long so as not to have an empty extension last (WebSphere 7.x,
+ * 8.x are intolerant of that condition)
+ */
+ if (hlen > 4)
+ hlen -= 4;
+ else
+ hlen = 1;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
+ || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ memset(padbytes, 0, hlen);
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+/*
+ * Construct the pre_shared_key extension
+ */
+EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ uint32_t now, agesec, agems = 0;
+ size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen;
+ unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL;
+ const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL;
+ int dores = 0;
+
s->ext.tick_identity = 0;
-
- /*
- * Note: At this stage of the code we only support adding a single
- * resumption PSK. If we add support for multiple PSKs then the length
- * calculations in the padding extension will need to be adjusted.
- */
-
- /*
- * If this is an incompatible or new session then we have nothing to resume
- * so don't add this extension.
- */
- if (s->session->ssl_version != TLS1_3_VERSION
- || (s->session->ext.ticklen == 0 && s->psksession == NULL))
- return EXT_RETURN_NOT_SENT;
-
- if (s->hello_retry_request == SSL_HRR_PENDING)
- handmd = ssl_handshake_md(s);
-
- if (s->session->ext.ticklen != 0) {
- /* Get the digest associated with the ciphersuite in the session */
- if (s->session->cipher == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- mdres = ssl_md(s->session->cipher->algorithm2);
- if (mdres == NULL) {
- /*
- * Don't recognize this cipher so we can't use the session.
- * Ignore it
- */
- goto dopsksess;
- }
-
- if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) {
- /*
- * Selected ciphersuite hash does not match the hash for the session
- * so we can't use it.
- */
- goto dopsksess;
- }
-
- /*
- * Technically the C standard just says time() returns a time_t and says
- * nothing about the encoding of that type. In practice most
- * implementations follow POSIX which holds it as an integral type in
- * seconds since epoch. We've already made the assumption that we can do
- * this in multiple places in the code, so portability shouldn't be an
- * issue.
- */
- now = (uint32_t)time(NULL);
- agesec = now - (uint32_t)s->session->time;
- /*
- * We calculate the age in seconds but the server may work in ms. Due to
- * rounding errors we could overestimate the age by up to 1s. It is
- * better to underestimate it. Otherwise, if the RTT is very short, when
- * the server calculates the age reported by the client it could be
- * bigger than the age calculated on the server - which should never
- * happen.
- */
- if (agesec > 0)
- agesec--;
-
- if (s->session->ext.tick_lifetime_hint < agesec) {
- /* Ticket is too old. Ignore it. */
- goto dopsksess;
- }
-
- /*
- * Calculate age in ms. We're just doing it to nearest second. Should be
- * good enough.
- */
- agems = agesec * (uint32_t)1000;
-
- if (agesec != 0 && agems / (uint32_t)1000 != agesec) {
- /*
- * Overflow. Shouldn't happen unless this is a *really* old session.
- * If so we just ignore it.
- */
- goto dopsksess;
- }
-
- /*
- * Obfuscate the age. Overflow here is fine, this addition is supposed
- * to be mod 2^32.
- */
- agems += s->session->ext.tick_age_add;
-
- reshashsize = EVP_MD_size(mdres);
+
+ /*
+ * Note: At this stage of the code we only support adding a single
+ * resumption PSK. If we add support for multiple PSKs then the length
+ * calculations in the padding extension will need to be adjusted.
+ */
+
+ /*
+ * If this is an incompatible or new session then we have nothing to resume
+ * so don't add this extension.
+ */
+ if (s->session->ssl_version != TLS1_3_VERSION
+ || (s->session->ext.ticklen == 0 && s->psksession == NULL))
+ return EXT_RETURN_NOT_SENT;
+
+ if (s->hello_retry_request == SSL_HRR_PENDING)
+ handmd = ssl_handshake_md(s);
+
+ if (s->session->ext.ticklen != 0) {
+ /* Get the digest associated with the ciphersuite in the session */
+ if (s->session->cipher == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ mdres = ssl_md(s->session->cipher->algorithm2);
+ if (mdres == NULL) {
+ /*
+ * Don't recognize this cipher so we can't use the session.
+ * Ignore it
+ */
+ goto dopsksess;
+ }
+
+ if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) {
+ /*
+ * Selected ciphersuite hash does not match the hash for the session
+ * so we can't use it.
+ */
+ goto dopsksess;
+ }
+
+ /*
+ * Technically the C standard just says time() returns a time_t and says
+ * nothing about the encoding of that type. In practice most
+ * implementations follow POSIX which holds it as an integral type in
+ * seconds since epoch. We've already made the assumption that we can do
+ * this in multiple places in the code, so portability shouldn't be an
+ * issue.
+ */
+ now = (uint32_t)time(NULL);
+ agesec = now - (uint32_t)s->session->time;
+ /*
+ * We calculate the age in seconds but the server may work in ms. Due to
+ * rounding errors we could overestimate the age by up to 1s. It is
+ * better to underestimate it. Otherwise, if the RTT is very short, when
+ * the server calculates the age reported by the client it could be
+ * bigger than the age calculated on the server - which should never
+ * happen.
+ */
+ if (agesec > 0)
+ agesec--;
+
+ if (s->session->ext.tick_lifetime_hint < agesec) {
+ /* Ticket is too old. Ignore it. */
+ goto dopsksess;
+ }
+
+ /*
+ * Calculate age in ms. We're just doing it to nearest second. Should be
+ * good enough.
+ */
+ agems = agesec * (uint32_t)1000;
+
+ if (agesec != 0 && agems / (uint32_t)1000 != agesec) {
+ /*
+ * Overflow. Shouldn't happen unless this is a *really* old session.
+ * If so we just ignore it.
+ */
+ goto dopsksess;
+ }
+
+ /*
+ * Obfuscate the age. Overflow here is fine, this addition is supposed
+ * to be mod 2^32.
+ */
+ agems += s->session->ext.tick_age_add;
+
+ reshashsize = EVP_MD_size(mdres);
s->ext.tick_identity++;
- dores = 1;
- }
-
- dopsksess:
- if (!dores && s->psksession == NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (s->psksession != NULL) {
- mdpsk = ssl_md(s->psksession->cipher->algorithm2);
- if (mdpsk == NULL) {
- /*
- * Don't recognize this cipher so we can't use the session.
- * If this happens it's an application bug.
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- SSL_R_BAD_PSK);
- return EXT_RETURN_FAIL;
- }
-
- if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) {
- /*
- * Selected ciphersuite hash does not match the hash for the PSK
- * session. This is an application bug.
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- SSL_R_BAD_PSK);
- return EXT_RETURN_FAIL;
- }
-
- pskhashsize = EVP_MD_size(mdpsk);
- }
-
- /* Create the extension, but skip over the binder for now */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- if (dores) {
- if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
- s->session->ext.ticklen)
- || !WPACKET_put_bytes_u32(pkt, agems)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- }
-
- if (s->psksession != NULL) {
- if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id,
- s->psksession_id_len)
- || !WPACKET_put_bytes_u32(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
+ dores = 1;
+ }
+
+ dopsksess:
+ if (!dores && s->psksession == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (s->psksession != NULL) {
+ mdpsk = ssl_md(s->psksession->cipher->algorithm2);
+ if (mdpsk == NULL) {
+ /*
+ * Don't recognize this cipher so we can't use the session.
+ * If this happens it's an application bug.
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+ SSL_R_BAD_PSK);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) {
+ /*
+ * Selected ciphersuite hash does not match the hash for the PSK
+ * session. This is an application bug.
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+ SSL_R_BAD_PSK);
+ return EXT_RETURN_FAIL;
+ }
+
+ pskhashsize = EVP_MD_size(mdpsk);
+ }
+
+ /* Create the extension, but skip over the binder for now */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (dores) {
+ if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
+ s->session->ext.ticklen)
+ || !WPACKET_put_bytes_u32(pkt, agems)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ }
+
+ if (s->psksession != NULL) {
+ if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id,
+ s->psksession_id_len)
+ || !WPACKET_put_bytes_u32(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
s->ext.tick_identity++;
- }
-
- if (!WPACKET_close(pkt)
- || !WPACKET_get_total_written(pkt, &binderoffset)
- || !WPACKET_start_sub_packet_u16(pkt)
- || (dores
- && !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder))
- || (s->psksession != NULL
- && !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder))
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)
- || !WPACKET_get_total_written(pkt, &msglen)
- /*
- * We need to fill in all the sub-packet lengths now so we can
- * calculate the HMAC of the message up to the binders
- */
- || !WPACKET_fill_lengths(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- msgstart = WPACKET_get_curr(pkt) - msglen;
-
- if (dores
- && tls_psk_do_binder(s, mdres, msgstart, binderoffset, NULL,
- resbinder, s->session, 1, 0) != 1) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
- }
-
- if (s->psksession != NULL
- && tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL,
- pskbinder, s->psksession, 1, 1) != 1) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-#else
- return EXT_RETURN_NOT_SENT;
-#endif
-}
-
-EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
- unsigned int context,
- X509 *x, size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- if (!s->pha_enabled)
- return EXT_RETURN_NOT_SENT;
-
- /* construct extension - 0 length, no contents */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- s->post_handshake_auth = SSL_PHA_EXT_SENT;
-
- return EXT_RETURN_SENT;
-#else
- return EXT_RETURN_NOT_SENT;
-#endif
-}
-
-
-/*
- * Parse the server's renegotiation binding and abort if it's not right
- */
-int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- size_t expected_len = s->s3->previous_client_finished_len
- + s->s3->previous_server_finished_len;
- size_t ilen;
- const unsigned char *data;
-
- /* Check for logic errors */
- if (!ossl_assert(expected_len == 0
- || s->s3->previous_client_finished_len != 0)
- || !ossl_assert(expected_len == 0
- || s->s3->previous_server_finished_len != 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* Parse the length byte */
- if (!PACKET_get_1_len(pkt, &ilen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_ENCODING_ERR);
- return 0;
- }
-
- /* Consistency check */
- if (PACKET_remaining(pkt) != ilen) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_ENCODING_ERR);
- return 0;
- }
-
- /* Check that the extension matches */
- if (ilen != expected_len) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
- return 0;
- }
-
- if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len)
- || memcmp(data, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
- return 0;
- }
-
- if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len)
- || memcmp(data, s->s3->previous_server_finished,
- s->s3->previous_server_finished_len) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
- return 0;
- }
- s->s3->send_connection_binding = 1;
-
- return 1;
-}
-
-/* Parse the server's max fragment len extension packet */
-int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- unsigned int value;
-
- if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- /* |value| should contains a valid max-fragment-length code. */
- if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
- SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
- return 0;
- }
-
- /* Must be the same value as client-configured one who was sent to server */
- /*-
- * RFC 6066: if a client receives a maximum fragment length negotiation
- * response that differs from the length it requested, ...
- * It must abort with SSL_AD_ILLEGAL_PARAMETER alert
- */
- if (value != s->ext.max_fragment_len_mode) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
- SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
- return 0;
- }
-
- /*
- * Maximum Fragment Length Negotiation succeeded.
- * The negotiated Maximum Fragment Length is binding now.
- */
- s->session->ext.max_fragment_len_mode = value;
-
- return 1;
-}
-
-int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (s->ext.hostname == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!s->hit) {
- if (s->session->ext.hostname != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
- if (s->session->ext.hostname == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_EC
-int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- size_t ecpointformats_len;
- PACKET ecptformatlist;
-
- if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
- if (!s->hit) {
- ecpointformats_len = PACKET_remaining(&ecptformatlist);
- if (ecpointformats_len == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH);
- return 0;
- }
-
+ }
+
+ if (!WPACKET_close(pkt)
+ || !WPACKET_get_total_written(pkt, &binderoffset)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || (dores
+ && !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder))
+ || (s->psksession != NULL
+ && !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder))
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)
+ || !WPACKET_get_total_written(pkt, &msglen)
+ /*
+ * We need to fill in all the sub-packet lengths now so we can
+ * calculate the HMAC of the message up to the binders
+ */
+ || !WPACKET_fill_lengths(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ msgstart = WPACKET_get_curr(pkt) - msglen;
+
+ if (dores
+ && tls_psk_do_binder(s, mdres, msgstart, binderoffset, NULL,
+ resbinder, s->session, 1, 0) != 1) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+
+ if (s->psksession != NULL
+ && tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL,
+ pskbinder, s->psksession, 1, 1) != 1) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+#else
+ return EXT_RETURN_NOT_SENT;
+#endif
+}
+
+EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
+ unsigned int context,
+ X509 *x, size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ if (!s->pha_enabled)
+ return EXT_RETURN_NOT_SENT;
+
+ /* construct extension - 0 length, no contents */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ s->post_handshake_auth = SSL_PHA_EXT_SENT;
+
+ return EXT_RETURN_SENT;
+#else
+ return EXT_RETURN_NOT_SENT;
+#endif
+}
+
+
+/*
+ * Parse the server's renegotiation binding and abort if it's not right
+ */
+int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ size_t expected_len = s->s3->previous_client_finished_len
+ + s->s3->previous_server_finished_len;
+ size_t ilen;
+ const unsigned char *data;
+
+ /* Check for logic errors */
+ if (!ossl_assert(expected_len == 0
+ || s->s3->previous_client_finished_len != 0)
+ || !ossl_assert(expected_len == 0
+ || s->s3->previous_server_finished_len != 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Parse the length byte */
+ if (!PACKET_get_1_len(pkt, &ilen)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ return 0;
+ }
+
+ /* Consistency check */
+ if (PACKET_remaining(pkt) != ilen) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ return 0;
+ }
+
+ /* Check that the extension matches */
+ if (ilen != expected_len) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ return 0;
+ }
+
+ if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len)
+ || memcmp(data, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ return 0;
+ }
+
+ if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len)
+ || memcmp(data, s->s3->previous_server_finished,
+ s->s3->previous_server_finished_len) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ return 0;
+ }
+ s->s3->send_connection_binding = 1;
+
+ return 1;
+}
+
+/* Parse the server's max fragment len extension packet */
+int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ unsigned int value;
+
+ if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ /* |value| should contains a valid max-fragment-length code. */
+ if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
+ SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+
+ /* Must be the same value as client-configured one who was sent to server */
+ /*-
+ * RFC 6066: if a client receives a maximum fragment length negotiation
+ * response that differs from the length it requested, ...
+ * It must abort with SSL_AD_ILLEGAL_PARAMETER alert
+ */
+ if (value != s->ext.max_fragment_len_mode) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
+ SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+
+ /*
+ * Maximum Fragment Length Negotiation succeeded.
+ * The negotiated Maximum Fragment Length is binding now.
+ */
+ s->session->ext.max_fragment_len_mode = value;
+
+ return 1;
+}
+
+int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (s->ext.hostname == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (PACKET_remaining(pkt) > 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!s->hit) {
+ if (s->session->ext.hostname != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
+ if (s->session->ext.hostname == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ size_t ecpointformats_len;
+ PACKET ecptformatlist;
+
+ if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ if (!s->hit) {
+ ecpointformats_len = PACKET_remaining(&ecptformatlist);
+ if (ecpointformats_len == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH);
+ return 0;
+ }
+
s->ext.peer_ecpointformats_len = 0;
OPENSSL_free(s->ext.peer_ecpointformats);
s->ext.peer_ecpointformats = OPENSSL_malloc(ecpointformats_len);
if (s->ext.peer_ecpointformats == NULL) {
s->ext.peer_ecpointformats_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
s->ext.peer_ecpointformats_len = ecpointformats_len;
-
- if (!PACKET_copy_bytes(&ecptformatlist,
+
+ if (!PACKET_copy_bytes(&ecptformatlist,
s->ext.peer_ecpointformats,
- ecpointformats_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- return 1;
-}
-#endif
-
-int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (s->ext.session_ticket_cb != NULL &&
- !s->ext.session_ticket_cb(s, PACKET_data(pkt),
- PACKET_remaining(pkt),
- s->ext.session_ticket_cb_arg)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!tls_use_ticket(s)) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
- SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
- return 0;
- }
- if (PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- s->ext.ticket_expected = 1;
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_OCSP
-int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
- /* We ignore this if the server sends a CertificateRequest */
- /* TODO(TLS1.3): Add support for this */
- return 1;
- }
-
- /*
- * MUST only be sent if we've requested a status
- * request message. In TLS <= 1.2 it must also be empty.
- */
- if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
- SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- return 0;
- }
- if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (SSL_IS_TLS13(s)) {
- /* We only know how to handle this if it's for the first Certificate in
- * the chain. We ignore any other responses.
- */
- if (chainidx != 0)
- return 1;
-
- /* SSLfatal() already called */
- return tls_process_cert_status_body(s, pkt);
- }
-
- /* Set flag to expect CertificateStatus message */
- s->ext.status_expected = 1;
-
- return 1;
-}
-#endif
-
-
-#ifndef OPENSSL_NO_CT
-int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
- /* We ignore this if the server sends it in a CertificateRequest */
- /* TODO(TLS1.3): Add support for this */
- return 1;
- }
-
- /*
- * Only take it if we asked for it - i.e if there is no CT validation
- * callback set, then a custom extension MAY be processing it, so we
- * need to let control continue to flow to that.
- */
- if (s->ct_validation_callback != NULL) {
- size_t size = PACKET_remaining(pkt);
-
- /* Simply copy it off for later processing */
- OPENSSL_free(s->ext.scts);
- s->ext.scts = NULL;
-
- s->ext.scts_len = (uint16_t)size;
- if (size > 0) {
- s->ext.scts = OPENSSL_malloc(size);
+ ecpointformats_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (s->ext.session_ticket_cb != NULL &&
+ !s->ext.session_ticket_cb(s, PACKET_data(pkt),
+ PACKET_remaining(pkt),
+ s->ext.session_ticket_cb_arg)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!tls_use_ticket(s)) {
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
+ SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ if (PACKET_remaining(pkt) > 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ s->ext.ticket_expected = 1;
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_OCSP
+int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
+ /* We ignore this if the server sends a CertificateRequest */
+ /* TODO(TLS1.3): Add support for this */
+ return 1;
+ }
+
+ /*
+ * MUST only be sent if we've requested a status
+ * request message. In TLS <= 1.2 it must also be empty.
+ */
+ if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
+ SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (SSL_IS_TLS13(s)) {
+ /* We only know how to handle this if it's for the first Certificate in
+ * the chain. We ignore any other responses.
+ */
+ if (chainidx != 0)
+ return 1;
+
+ /* SSLfatal() already called */
+ return tls_process_cert_status_body(s, pkt);
+ }
+
+ /* Set flag to expect CertificateStatus message */
+ s->ext.status_expected = 1;
+
+ return 1;
+}
+#endif
+
+
+#ifndef OPENSSL_NO_CT
+int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
+ /* We ignore this if the server sends it in a CertificateRequest */
+ /* TODO(TLS1.3): Add support for this */
+ return 1;
+ }
+
+ /*
+ * Only take it if we asked for it - i.e if there is no CT validation
+ * callback set, then a custom extension MAY be processing it, so we
+ * need to let control continue to flow to that.
+ */
+ if (s->ct_validation_callback != NULL) {
+ size_t size = PACKET_remaining(pkt);
+
+ /* Simply copy it off for later processing */
+ OPENSSL_free(s->ext.scts);
+ s->ext.scts = NULL;
+
+ s->ext.scts_len = (uint16_t)size;
+ if (size > 0) {
+ s->ext.scts = OPENSSL_malloc(size);
if (s->ext.scts == NULL) {
s->ext.scts_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
ERR_R_MALLOC_FAILURE);
return 0;
}
if (!PACKET_copy_bytes(pkt, s->ext.scts, size)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- } else {
- ENDPOINT role = (context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
- ? ENDPOINT_CLIENT : ENDPOINT_BOTH;
-
- /*
- * If we didn't ask for it then there must be a custom extension,
- * otherwise this is unsolicited.
- */
- if (custom_ext_find(&s->cert->custext, role,
- TLSEXT_TYPE_signed_certificate_timestamp,
- NULL) == NULL) {
- SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!custom_ext_parse(s, context,
- TLSEXT_TYPE_signed_certificate_timestamp,
- PACKET_data(pkt), PACKET_remaining(pkt),
- x, chainidx)) {
- /* SSLfatal already called */
- return 0;
- }
- }
-
- return 1;
-}
-#endif
-
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
-/*
- * ssl_next_proto_validate validates a Next Protocol Negotiation block. No
- * elements of zero length are allowed and the set of elements must exactly
- * fill the length of the block. Returns 1 on success or 0 on failure.
- */
-static int ssl_next_proto_validate(SSL *s, PACKET *pkt)
-{
- PACKET tmp_protocol;
-
- while (PACKET_remaining(pkt)) {
- if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol)
- || PACKET_remaining(&tmp_protocol) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
- }
-
- return 1;
-}
-
-int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- unsigned char *selected;
- unsigned char selected_len;
- PACKET tmppkt;
-
- /* Check if we are in a renegotiation. If so ignore this extension */
- if (!SSL_IS_FIRST_HANDSHAKE(s))
- return 1;
-
- /* We must have requested it. */
- if (s->ctx->ext.npn_select_cb == NULL) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- /* The data must be valid */
- tmppkt = *pkt;
- if (!ssl_next_proto_validate(s, &tmppkt)) {
- /* SSLfatal() already called */
- return 0;
- }
- if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len,
- PACKET_data(pkt),
- PACKET_remaining(pkt),
- s->ctx->ext.npn_select_cb_arg) !=
- SSL_TLSEXT_ERR_OK) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- /*
- * Could be non-NULL if server has sent multiple NPN extensions in
- * a single Serverhello
- */
- OPENSSL_free(s->ext.npn);
- s->ext.npn = OPENSSL_malloc(selected_len);
- if (s->ext.npn == NULL) {
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ } else {
+ ENDPOINT role = (context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
+ ? ENDPOINT_CLIENT : ENDPOINT_BOTH;
+
+ /*
+ * If we didn't ask for it then there must be a custom extension,
+ * otherwise this is unsolicited.
+ */
+ if (custom_ext_find(&s->cert->custext, role,
+ TLSEXT_TYPE_signed_certificate_timestamp,
+ NULL) == NULL) {
+ SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!custom_ext_parse(s, context,
+ TLSEXT_TYPE_signed_certificate_timestamp,
+ PACKET_data(pkt), PACKET_remaining(pkt),
+ x, chainidx)) {
+ /* SSLfatal already called */
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+/*
+ * ssl_next_proto_validate validates a Next Protocol Negotiation block. No
+ * elements of zero length are allowed and the set of elements must exactly
+ * fill the length of the block. Returns 1 on success or 0 on failure.
+ */
+static int ssl_next_proto_validate(SSL *s, PACKET *pkt)
+{
+ PACKET tmp_protocol;
+
+ while (PACKET_remaining(pkt)) {
+ if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol)
+ || PACKET_remaining(&tmp_protocol) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ unsigned char *selected;
+ unsigned char selected_len;
+ PACKET tmppkt;
+
+ /* Check if we are in a renegotiation. If so ignore this extension */
+ if (!SSL_IS_FIRST_HANDSHAKE(s))
+ return 1;
+
+ /* We must have requested it. */
+ if (s->ctx->ext.npn_select_cb == NULL) {
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ /* The data must be valid */
+ tmppkt = *pkt;
+ if (!ssl_next_proto_validate(s, &tmppkt)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len,
+ PACKET_data(pkt),
+ PACKET_remaining(pkt),
+ s->ctx->ext.npn_select_cb_arg) !=
+ SSL_TLSEXT_ERR_OK) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ /*
+ * Could be non-NULL if server has sent multiple NPN extensions in
+ * a single Serverhello
+ */
+ OPENSSL_free(s->ext.npn);
+ s->ext.npn = OPENSSL_malloc(selected_len);
+ if (s->ext.npn == NULL) {
s->ext.npn_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- memcpy(s->ext.npn, selected, selected_len);
- s->ext.npn_len = selected_len;
- s->s3->npn_seen = 1;
-
- return 1;
-}
-#endif
-
-int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- size_t len;
-
- /* We must have requested it. */
- if (!s->s3->alpn_sent) {
- SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
- /*-
- * The extension data consists of:
- * uint16 list_length
- * uint8 proto_length;
- * uint8 proto[proto_length];
- */
- if (!PACKET_get_net_2_len(pkt, &len)
- || PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len)
- || PACKET_remaining(pkt) != len) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
- OPENSSL_free(s->s3->alpn_selected);
- s->s3->alpn_selected = OPENSSL_malloc(len);
- if (s->s3->alpn_selected == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ memcpy(s->ext.npn, selected, selected_len);
+ s->ext.npn_len = selected_len;
+ s->s3->npn_seen = 1;
+
+ return 1;
+}
+#endif
+
+int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ size_t len;
+
+ /* We must have requested it. */
+ if (!s->s3->alpn_sent) {
+ SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ /*-
+ * The extension data consists of:
+ * uint16 list_length
+ * uint8 proto_length;
+ * uint8 proto[proto_length];
+ */
+ if (!PACKET_get_net_2_len(pkt, &len)
+ || PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len)
+ || PACKET_remaining(pkt) != len) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = OPENSSL_malloc(len);
+ if (s->s3->alpn_selected == NULL) {
s->s3->alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
- s->s3->alpn_selected_len = len;
-
- if (s->session->ext.alpn_selected == NULL
- || s->session->ext.alpn_selected_len != len
- || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len)
- != 0) {
- /* ALPN not consistent with the old session so cannot use early_data */
- s->ext.early_data_ok = 0;
- }
- if (!s->hit) {
- /*
- * This is a new session and so alpn_selected should have been
- * initialised to NULL. We should update it with the selected ALPN.
- */
- if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->session->ext.alpn_selected =
- OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
- if (s->session->ext.alpn_selected == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ s->s3->alpn_selected_len = len;
+
+ if (s->session->ext.alpn_selected == NULL
+ || s->session->ext.alpn_selected_len != len
+ || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len)
+ != 0) {
+ /* ALPN not consistent with the old session so cannot use early_data */
+ s->ext.early_data_ok = 0;
+ }
+ if (!s->hit) {
+ /*
+ * This is a new session and so alpn_selected should have been
+ * initialised to NULL. We should update it with the selected ALPN.
+ */
+ if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->session->ext.alpn_selected =
+ OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
+ if (s->session->ext.alpn_selected == NULL) {
s->session->ext.alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
- }
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_SRTP
-int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- unsigned int id, ct, mki;
- int i;
- STACK_OF(SRTP_PROTECTION_PROFILE) *clnt;
- SRTP_PROTECTION_PROFILE *prof;
-
- if (!PACKET_get_net_2(pkt, &ct) || ct != 2
- || !PACKET_get_net_2(pkt, &id)
- || !PACKET_get_1(pkt, &mki)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- return 0;
- }
-
- if (mki != 0) {
- /* Must be no MKI, since we never offer one */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP,
- SSL_R_BAD_SRTP_MKI_VALUE);
- return 0;
- }
-
- /* Throw an error if the server gave us an unsolicited extension */
- clnt = SSL_get_srtp_profiles(s);
- if (clnt == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
- SSL_R_NO_SRTP_PROFILES);
- return 0;
- }
-
- /*
- * Check to see if the server gave us something we support (and
- * presumably offered)
- */
- for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) {
- prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
-
- if (prof->id == id) {
- s->srtp_profile = prof;
- return 1;
- }
- }
-
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- return 0;
-}
-#endif
-
-int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- /* Ignore if inappropriate ciphersuite */
- if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
- && s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
- && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
- s->ext.use_etm = 1;
-
- return 1;
-}
-
-int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
- if (!s->hit)
- s->session->flags |= SSL_SESS_FLAG_EXTMS;
-
- return 1;
-}
-
-int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- unsigned int version;
-
- if (!PACKET_get_net_2(pkt, &version)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- /*
- * The only protocol version we support which is valid in this extension in
- * a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else.
- */
- if (version != TLS1_3_VERSION) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
- SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
- return 0;
- }
-
- /* We ignore this extension for HRRs except to sanity check it */
- if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)
- return 1;
-
- /* We just set it here. We validate it in ssl_choose_client_version */
- s->version = version;
-
- return 1;
-}
-
-int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- unsigned int group_id;
- PACKET encoded_pt;
- EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL;
-
- /* Sanity check */
- if (ckey == NULL || s->s3->peer_tmp != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!PACKET_get_net_2(pkt, &group_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) {
- const uint16_t *pgroups = NULL;
- size_t i, num_groups;
-
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- /*
- * It is an error if the HelloRetryRequest wants a key_share that we
- * already sent in the first ClientHello
- */
- if (group_id == s->s3->group_id) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
- return 0;
- }
-
- /* Validate the selected group is one we support */
- tls1_get_supported_groups(s, &pgroups, &num_groups);
- for (i = 0; i < num_groups; i++) {
- if (group_id == pgroups[i])
- break;
- }
- if (i >= num_groups
- || !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
- return 0;
- }
-
- s->s3->group_id = group_id;
- EVP_PKEY_free(s->s3->tmp.pkey);
- s->s3->tmp.pkey = NULL;
- return 1;
- }
-
- if (group_id != s->s3->group_id) {
- /*
- * This isn't for the group that we sent in the original
- * key_share!
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_BAD_KEY_SHARE);
- return 0;
- }
-
- if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
- || PACKET_remaining(&encoded_pt) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRTP
+int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ unsigned int id, ct, mki;
+ int i;
+ STACK_OF(SRTP_PROTECTION_PROFILE) *clnt;
+ SRTP_PROTECTION_PROFILE *prof;
+
+ if (!PACKET_get_net_2(pkt, &ct) || ct != 2
+ || !PACKET_get_net_2(pkt, &id)
+ || !PACKET_get_1(pkt, &mki)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ return 0;
+ }
+
+ if (mki != 0) {
+ /* Must be no MKI, since we never offer one */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+ SSL_R_BAD_SRTP_MKI_VALUE);
+ return 0;
+ }
+
+ /* Throw an error if the server gave us an unsolicited extension */
+ clnt = SSL_get_srtp_profiles(s);
+ if (clnt == NULL) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+ SSL_R_NO_SRTP_PROFILES);
+ return 0;
+ }
+
+ /*
+ * Check to see if the server gave us something we support (and
+ * presumably offered)
+ */
+ for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) {
+ prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
+
+ if (prof->id == id) {
+ s->srtp_profile = prof;
+ return 1;
+ }
+ }
+
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ return 0;
+}
+#endif
+
+int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ /* Ignore if inappropriate ciphersuite */
+ if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
+ && s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
+ && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
+ s->ext.use_etm = 1;
+
+ return 1;
+}
+
+int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
+ if (!s->hit)
+ s->session->flags |= SSL_SESS_FLAG_EXTMS;
+
+ return 1;
+}
+
+int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ unsigned int version;
+
+ if (!PACKET_get_net_2(pkt, &version)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /*
+ * The only protocol version we support which is valid in this extension in
+ * a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else.
+ */
+ if (version != TLS1_3_VERSION) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
+ SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
+ return 0;
+ }
+
+ /* We ignore this extension for HRRs except to sanity check it */
+ if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)
+ return 1;
+
+ /* We just set it here. We validate it in ssl_choose_client_version */
+ s->version = version;
+
+ return 1;
+}
+
+int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ unsigned int group_id;
+ PACKET encoded_pt;
+ EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL;
+
+ /* Sanity check */
+ if (ckey == NULL || s->s3->peer_tmp != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!PACKET_get_net_2(pkt, &group_id)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) {
+ const uint16_t *pgroups = NULL;
+ size_t i, num_groups;
+
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /*
+ * It is an error if the HelloRetryRequest wants a key_share that we
+ * already sent in the first ClientHello
+ */
+ if (group_id == s->s3->group_id) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+ return 0;
+ }
+
+ /* Validate the selected group is one we support */
+ tls1_get_supported_groups(s, &pgroups, &num_groups);
+ for (i = 0; i < num_groups; i++) {
+ if (group_id == pgroups[i])
+ break;
+ }
+ if (i >= num_groups
+ || !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+ return 0;
+ }
+
+ s->s3->group_id = group_id;
+ EVP_PKEY_free(s->s3->tmp.pkey);
+ s->s3->tmp.pkey = NULL;
+ return 1;
+ }
+
+ if (group_id != s->s3->group_id) {
+ /*
+ * This isn't for the group that we sent in the original
+ * key_share!
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+ SSL_R_BAD_KEY_SHARE);
+ return 0;
+ }
+
+ if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
+ || PACKET_remaining(&encoded_pt) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
skey = EVP_PKEY_new();
if (skey == NULL || EVP_PKEY_copy_parameters(skey, ckey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
- PACKET_remaining(&encoded_pt))) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
- SSL_R_BAD_ECPOINT);
- EVP_PKEY_free(skey);
- return 0;
- }
-
- if (ssl_derive(s, ckey, skey, 1) == 0) {
- /* SSLfatal() already called */
- EVP_PKEY_free(skey);
- return 0;
- }
- s->s3->peer_tmp = skey;
-#endif
-
- return 1;
-}
-
-int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- PACKET cookie;
-
- if (!PACKET_as_length_prefixed_2(pkt, &cookie)
- || !PACKET_memdup(&cookie, &s->ext.tls13_cookie,
- &s->ext.tls13_cookie_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- return 1;
-}
-
-int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
- unsigned long max_early_data;
-
- if (!PACKET_get_net_4(pkt, &max_early_data)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
- SSL_R_INVALID_MAX_EARLY_DATA);
- return 0;
- }
-
- s->session->ext.max_early_data = max_early_data;
-
- return 1;
- }
-
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!s->ext.early_data_ok
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
+ PACKET_remaining(&encoded_pt))) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+ SSL_R_BAD_ECPOINT);
+ EVP_PKEY_free(skey);
+ return 0;
+ }
+
+ if (ssl_derive(s, ckey, skey, 1) == 0) {
+ /* SSLfatal() already called */
+ EVP_PKEY_free(skey);
+ return 0;
+ }
+ s->s3->peer_tmp = skey;
+#endif
+
+ return 1;
+}
+
+int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ PACKET cookie;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &cookie)
+ || !PACKET_memdup(&cookie, &s->ext.tls13_cookie,
+ &s->ext.tls13_cookie_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
+ unsigned long max_early_data;
+
+ if (!PACKET_get_net_4(pkt, &max_early_data)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
+ SSL_R_INVALID_MAX_EARLY_DATA);
+ return 0;
+ }
+
+ s->session->ext.max_early_data = max_early_data;
+
+ return 1;
+ }
+
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!s->ext.early_data_ok
|| !s->hit) {
- /*
- * If we get here then we didn't send early data, or we didn't resume
- * using the first identity, or the SNI/ALPN is not consistent so the
- * server should not be accepting it.
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
-
- return 1;
-}
-
-int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- unsigned int identity;
-
- if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
+ /*
+ * If we get here then we didn't send early data, or we didn't resume
+ * using the first identity, or the SNI/ALPN is not consistent so the
+ * server should not be accepting it.
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
+
+ return 1;
+}
+
+int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ unsigned int identity;
+
+ if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
if (identity >= (unsigned int)s->ext.tick_identity) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
SSL_R_BAD_PSK_IDENTITY);
@@ -1974,38 +1974,38 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
* sent two tickets, or if we didn't send a PSK ticket.
*/
if (identity == 0 && (s->psksession == NULL || s->ext.tick_identity == 2)) {
- s->hit = 1;
- SSL_SESSION_free(s->psksession);
- s->psksession = NULL;
- return 1;
- }
-
+ s->hit = 1;
+ SSL_SESSION_free(s->psksession);
+ s->psksession = NULL;
+ return 1;
+ }
+
if (s->psksession == NULL) {
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * If we used the external PSK for sending early_data then s->early_secret
- * is already set up, so don't overwrite it. Otherwise we copy the
- * early_secret across that we generated earlier.
- */
- if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
- && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
- || s->session->ext.max_early_data > 0
- || s->psksession->ext.max_early_data == 0)
- memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE);
-
- SSL_SESSION_free(s->session);
- s->session = s->psksession;
- s->psksession = NULL;
- s->hit = 1;
+ return 0;
+ }
+
+ /*
+ * If we used the external PSK for sending early_data then s->early_secret
+ * is already set up, so don't overwrite it. Otherwise we copy the
+ * early_secret across that we generated earlier.
+ */
+ if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
+ && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
+ || s->session->ext.max_early_data > 0
+ || s->psksession->ext.max_early_data == 0)
+ memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE);
+
+ SSL_SESSION_free(s->session);
+ s->session = s->psksession;
+ s->psksession = NULL;
+ s->hit = 1;
/* Early data is only allowed if we used the first ticket */
if (identity != 0)
s->ext.early_data_ok = 0;
-#endif
-
- return 1;
-}
+#endif
+
+ return 1;
+}
diff --git a/contrib/libs/openssl/ssl/statem/extensions_cust.c b/contrib/libs/openssl/ssl/statem/extensions_cust.c
index a0ba18efa7..e76b2e6a48 100644
--- a/contrib/libs/openssl/ssl/statem/extensions_cust.c
+++ b/contrib/libs/openssl/ssl/statem/extensions_cust.c
@@ -1,533 +1,533 @@
-/*
- * Copyright 2014-2018 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
- */
-
-/* Custom extension utility functions */
-
-#include <openssl/ct.h>
+/*
+ * Copyright 2014-2018 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
+ */
+
+/* Custom extension utility functions */
+
+#include <openssl/ct.h>
#include "../ssl_local.h"
-#include "internal/cryptlib.h"
+#include "internal/cryptlib.h"
#include "statem_local.h"
-
-typedef struct {
- void *add_arg;
- custom_ext_add_cb add_cb;
- custom_ext_free_cb free_cb;
-} custom_ext_add_cb_wrap;
-
-typedef struct {
- void *parse_arg;
- custom_ext_parse_cb parse_cb;
-} custom_ext_parse_cb_wrap;
-
-/*
- * Provide thin wrapper callbacks which convert new style arguments to old style
- */
-static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char **out,
- size_t *outlen, X509 *x, size_t chainidx,
- int *al, void *add_arg)
-{
- custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
-
- if (add_cb_wrap->add_cb == NULL)
- return 1;
-
- return add_cb_wrap->add_cb(s, ext_type, out, outlen, al,
- add_cb_wrap->add_arg);
-}
-
-static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *out, void *add_arg)
-{
- custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
-
- if (add_cb_wrap->free_cb == NULL)
- return;
-
- add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg);
-}
-
-static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *in,
- size_t inlen, X509 *x, size_t chainidx,
- int *al, void *parse_arg)
-{
- custom_ext_parse_cb_wrap *parse_cb_wrap =
- (custom_ext_parse_cb_wrap *)parse_arg;
-
- if (parse_cb_wrap->parse_cb == NULL)
- return 1;
-
- return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al,
- parse_cb_wrap->parse_arg);
-}
-
-/*
- * Find a custom extension from the list. The |role| param is there to
- * support the legacy API where custom extensions for client and server could
- * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we
- * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the
- * client, or ENDPOINT_BOTH for either
- */
-custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
- ENDPOINT role, unsigned int ext_type,
- size_t *idx)
-{
- size_t i;
- custom_ext_method *meth = exts->meths;
-
- for (i = 0; i < exts->meths_count; i++, meth++) {
- if (ext_type == meth->ext_type
- && (role == ENDPOINT_BOTH || role == meth->role
- || meth->role == ENDPOINT_BOTH)) {
- if (idx != NULL)
- *idx = i;
- return meth;
- }
- }
- return NULL;
-}
-
-/*
- * Initialise custom extensions flags to indicate neither sent nor received.
- */
-void custom_ext_init(custom_ext_methods *exts)
-{
- size_t i;
- custom_ext_method *meth = exts->meths;
-
- for (i = 0; i < exts->meths_count; i++, meth++)
- meth->ext_flags = 0;
-}
-
-/* Pass received custom extension data to the application for parsing. */
-int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
- const unsigned char *ext_data, size_t ext_size, X509 *x,
- size_t chainidx)
-{
- int al;
- custom_ext_methods *exts = &s->cert->custext;
- custom_ext_method *meth;
- ENDPOINT role = ENDPOINT_BOTH;
-
- if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0)
- role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT;
-
- meth = custom_ext_find(exts, role, ext_type, NULL);
- /* If not found return success */
- if (!meth)
- return 1;
-
- /* Check if extension is defined for our protocol. If not, skip */
- if (!extension_is_relevant(s, meth->context, context))
- return 1;
-
- if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_SERVER_HELLO
- | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
- /*
- * If it's ServerHello or EncryptedExtensions we can't have any
- * extensions not sent in ClientHello.
- */
- if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
- SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
- }
-
- /*
- * Extensions received in the ClientHello are marked with the
- * SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
- * extensions in the ServerHello/EncryptedExtensions message
- */
- if ((context & SSL_EXT_CLIENT_HELLO) != 0)
- meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;
-
- /* If no parse function set return success */
- if (!meth->parse_cb)
- return 1;
-
- if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
- &al, meth->parse_arg) <= 0) {
- SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Request custom extension data from the application and add to the return
- * buffer.
- */
-int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
- int maxversion)
-{
- custom_ext_methods *exts = &s->cert->custext;
- custom_ext_method *meth;
- size_t i;
- int al;
-
- for (i = 0; i < exts->meths_count; i++) {
- const unsigned char *out = NULL;
- size_t outlen = 0;
-
- meth = exts->meths + i;
-
- if (!should_add_extension(s, meth->context, context, maxversion))
- continue;
-
- if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_SERVER_HELLO
- | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
- | SSL_EXT_TLS1_3_CERTIFICATE
- | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
- /* Only send extensions present in ClientHello. */
- if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
- continue;
- }
- /*
- * We skip it if the callback is absent - except for a ClientHello where
- * we add an empty extension.
- */
- if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL)
- continue;
-
- if (meth->add_cb != NULL) {
- int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
- &outlen, x, chainidx, &al,
- meth->add_arg);
-
- if (cb_retval < 0) {
- SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED);
- return 0; /* error */
- }
- if (cb_retval == 0)
- continue; /* skip this extension */
- }
-
- if (!WPACKET_put_bytes_u16(pkt, meth->ext_type)
- || !WPACKET_start_sub_packet_u16(pkt)
- || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
- /*
- * We can't send duplicates: code logic should prevent this.
- */
- if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- /*
- * Indicate extension has been sent: this is both a sanity check to
- * ensure we don't send duplicate extensions and indicates that it
- * is not an error if the extension is present in ServerHello.
- */
- meth->ext_flags |= SSL_EXT_FLAG_SENT;
- }
- if (meth->free_cb != NULL)
- meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
- }
- return 1;
-}
-
-/* Copy the flags from src to dst for any extensions that exist in both */
-int custom_exts_copy_flags(custom_ext_methods *dst,
- const custom_ext_methods *src)
-{
- size_t i;
- custom_ext_method *methsrc = src->meths;
-
- for (i = 0; i < src->meths_count; i++, methsrc++) {
- custom_ext_method *methdst = custom_ext_find(dst, methsrc->role,
- methsrc->ext_type, NULL);
-
- if (methdst == NULL)
- continue;
-
- methdst->ext_flags = methsrc->ext_flags;
- }
-
- return 1;
-}
-
-/* Copy table of custom extensions */
-int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
-{
- size_t i;
- int err = 0;
-
- if (src->meths_count > 0) {
- dst->meths =
- OPENSSL_memdup(src->meths,
- sizeof(*src->meths) * src->meths_count);
- if (dst->meths == NULL)
- return 0;
- dst->meths_count = src->meths_count;
-
- for (i = 0; i < src->meths_count; i++) {
- custom_ext_method *methsrc = src->meths + i;
- custom_ext_method *methdst = dst->meths + i;
-
- if (methsrc->add_cb != custom_ext_add_old_cb_wrap)
- continue;
-
- /*
- * We have found an old style API wrapper. We need to copy the
- * arguments too.
- */
-
- if (err) {
- methdst->add_arg = NULL;
- methdst->parse_arg = NULL;
- continue;
- }
-
- methdst->add_arg = OPENSSL_memdup(methsrc->add_arg,
- sizeof(custom_ext_add_cb_wrap));
- methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg,
- sizeof(custom_ext_parse_cb_wrap));
-
- if (methdst->add_arg == NULL || methdst->parse_arg == NULL)
- err = 1;
- }
- }
-
- if (err) {
- custom_exts_free(dst);
- return 0;
- }
-
- return 1;
-}
-
-void custom_exts_free(custom_ext_methods *exts)
-{
- size_t i;
- custom_ext_method *meth;
-
- for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) {
- if (meth->add_cb != custom_ext_add_old_cb_wrap)
- continue;
-
- /* Old style API wrapper. Need to free the arguments too */
- OPENSSL_free(meth->add_arg);
- OPENSSL_free(meth->parse_arg);
- }
- OPENSSL_free(exts->meths);
-}
-
-/* Return true if a client custom extension exists, false otherwise */
-int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
-{
- return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type,
- NULL) != NULL;
-}
-
-static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role,
- unsigned int ext_type,
- unsigned int context,
- SSL_custom_ext_add_cb_ex add_cb,
- SSL_custom_ext_free_cb_ex free_cb,
- void *add_arg,
- SSL_custom_ext_parse_cb_ex parse_cb,
- void *parse_arg)
-{
- custom_ext_methods *exts = &ctx->cert->custext;
- custom_ext_method *meth, *tmp;
-
- /*
- * Check application error: if add_cb is not set free_cb will never be
- * called.
- */
- if (add_cb == NULL && free_cb != NULL)
- return 0;
-
-#ifndef OPENSSL_NO_CT
- /*
- * We don't want applications registering callbacks for SCT extensions
- * whilst simultaneously using the built-in SCT validation features, as
- * these two things may not play well together.
- */
- if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp
- && (context & SSL_EXT_CLIENT_HELLO) != 0
- && SSL_CTX_ct_is_enabled(ctx))
- return 0;
-#endif
-
- /*
- * Don't add if extension supported internally, but make exception
- * for extension types that previously were not supported, but now are.
- */
- if (SSL_extension_supported(ext_type)
- && ext_type != TLSEXT_TYPE_signed_certificate_timestamp)
- return 0;
-
- /* Extension type must fit in 16 bits */
- if (ext_type > 0xffff)
- return 0;
- /* Search for duplicate */
- if (custom_ext_find(exts, role, ext_type, NULL))
- return 0;
- tmp = OPENSSL_realloc(exts->meths,
- (exts->meths_count + 1) * sizeof(custom_ext_method));
- if (tmp == NULL)
- return 0;
-
- exts->meths = tmp;
- meth = exts->meths + exts->meths_count;
- memset(meth, 0, sizeof(*meth));
- meth->role = role;
- meth->context = context;
- meth->parse_cb = parse_cb;
- meth->add_cb = add_cb;
- meth->free_cb = free_cb;
- meth->ext_type = ext_type;
- meth->add_arg = add_arg;
- meth->parse_arg = parse_arg;
- exts->meths_count++;
- return 1;
-}
-
-static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role,
- unsigned int ext_type,
- unsigned int context,
- custom_ext_add_cb add_cb,
- custom_ext_free_cb free_cb,
- void *add_arg,
- custom_ext_parse_cb parse_cb, void *parse_arg)
-{
- custom_ext_add_cb_wrap *add_cb_wrap
- = OPENSSL_malloc(sizeof(*add_cb_wrap));
- custom_ext_parse_cb_wrap *parse_cb_wrap
- = OPENSSL_malloc(sizeof(*parse_cb_wrap));
- int ret;
-
- if (add_cb_wrap == NULL || parse_cb_wrap == NULL) {
- OPENSSL_free(add_cb_wrap);
- OPENSSL_free(parse_cb_wrap);
- return 0;
- }
-
- add_cb_wrap->add_arg = add_arg;
- add_cb_wrap->add_cb = add_cb;
- add_cb_wrap->free_cb = free_cb;
- parse_cb_wrap->parse_arg = parse_arg;
- parse_cb_wrap->parse_cb = parse_cb;
-
- ret = add_custom_ext_intern(ctx, role, ext_type,
- context,
- custom_ext_add_old_cb_wrap,
- custom_ext_free_old_cb_wrap,
- add_cb_wrap,
- custom_ext_parse_old_cb_wrap,
- parse_cb_wrap);
-
- if (!ret) {
- OPENSSL_free(add_cb_wrap);
- OPENSSL_free(parse_cb_wrap);
- }
-
- return ret;
-}
-
-/* Application level functions to add the old custom extension callbacks */
-int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
- custom_ext_add_cb add_cb,
- custom_ext_free_cb free_cb,
- void *add_arg,
- custom_ext_parse_cb parse_cb, void *parse_arg)
-{
- return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type,
- SSL_EXT_TLS1_2_AND_BELOW_ONLY
- | SSL_EXT_CLIENT_HELLO
- | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_IGNORE_ON_RESUMPTION,
- add_cb, free_cb, add_arg, parse_cb, parse_arg);
-}
-
-int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
- custom_ext_add_cb add_cb,
- custom_ext_free_cb free_cb,
- void *add_arg,
- custom_ext_parse_cb parse_cb, void *parse_arg)
-{
- return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type,
- SSL_EXT_TLS1_2_AND_BELOW_ONLY
- | SSL_EXT_CLIENT_HELLO
- | SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_IGNORE_ON_RESUMPTION,
- add_cb, free_cb, add_arg, parse_cb, parse_arg);
-}
-
-int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
- unsigned int context,
- SSL_custom_ext_add_cb_ex add_cb,
- SSL_custom_ext_free_cb_ex free_cb,
- void *add_arg,
- SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg)
-{
- return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb,
- free_cb, add_arg, parse_cb, parse_arg);
-}
-
-int SSL_extension_supported(unsigned int ext_type)
-{
- switch (ext_type) {
- /* Internally supported extensions. */
- case TLSEXT_TYPE_application_layer_protocol_negotiation:
-#ifndef OPENSSL_NO_EC
- case TLSEXT_TYPE_ec_point_formats:
- case TLSEXT_TYPE_supported_groups:
- case TLSEXT_TYPE_key_share:
-#endif
-#ifndef OPENSSL_NO_NEXTPROTONEG
- case TLSEXT_TYPE_next_proto_neg:
-#endif
- case TLSEXT_TYPE_padding:
- case TLSEXT_TYPE_renegotiate:
- case TLSEXT_TYPE_max_fragment_length:
- case TLSEXT_TYPE_server_name:
- case TLSEXT_TYPE_session_ticket:
- case TLSEXT_TYPE_signature_algorithms:
-#ifndef OPENSSL_NO_SRP
- case TLSEXT_TYPE_srp:
-#endif
-#ifndef OPENSSL_NO_OCSP
- case TLSEXT_TYPE_status_request:
-#endif
-#ifndef OPENSSL_NO_CT
- case TLSEXT_TYPE_signed_certificate_timestamp:
-#endif
-#ifndef OPENSSL_NO_SRTP
- case TLSEXT_TYPE_use_srtp:
-#endif
- case TLSEXT_TYPE_encrypt_then_mac:
- case TLSEXT_TYPE_supported_versions:
- case TLSEXT_TYPE_extended_master_secret:
- case TLSEXT_TYPE_psk_kex_modes:
- case TLSEXT_TYPE_cookie:
- case TLSEXT_TYPE_early_data:
- case TLSEXT_TYPE_certificate_authorities:
- case TLSEXT_TYPE_psk:
- case TLSEXT_TYPE_post_handshake_auth:
- return 1;
- default:
- return 0;
- }
-}
+
+typedef struct {
+ void *add_arg;
+ custom_ext_add_cb add_cb;
+ custom_ext_free_cb free_cb;
+} custom_ext_add_cb_wrap;
+
+typedef struct {
+ void *parse_arg;
+ custom_ext_parse_cb parse_cb;
+} custom_ext_parse_cb_wrap;
+
+/*
+ * Provide thin wrapper callbacks which convert new style arguments to old style
+ */
+static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char **out,
+ size_t *outlen, X509 *x, size_t chainidx,
+ int *al, void *add_arg)
+{
+ custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
+
+ if (add_cb_wrap->add_cb == NULL)
+ return 1;
+
+ return add_cb_wrap->add_cb(s, ext_type, out, outlen, al,
+ add_cb_wrap->add_arg);
+}
+
+static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char *out, void *add_arg)
+{
+ custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
+
+ if (add_cb_wrap->free_cb == NULL)
+ return;
+
+ add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg);
+}
+
+static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type,
+ unsigned int context,
+ const unsigned char *in,
+ size_t inlen, X509 *x, size_t chainidx,
+ int *al, void *parse_arg)
+{
+ custom_ext_parse_cb_wrap *parse_cb_wrap =
+ (custom_ext_parse_cb_wrap *)parse_arg;
+
+ if (parse_cb_wrap->parse_cb == NULL)
+ return 1;
+
+ return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al,
+ parse_cb_wrap->parse_arg);
+}
+
+/*
+ * Find a custom extension from the list. The |role| param is there to
+ * support the legacy API where custom extensions for client and server could
+ * be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we
+ * are trying to find a method relevant to the server, ENDPOINT_CLIENT for the
+ * client, or ENDPOINT_BOTH for either
+ */
+custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
+ ENDPOINT role, unsigned int ext_type,
+ size_t *idx)
+{
+ size_t i;
+ custom_ext_method *meth = exts->meths;
+
+ for (i = 0; i < exts->meths_count; i++, meth++) {
+ if (ext_type == meth->ext_type
+ && (role == ENDPOINT_BOTH || role == meth->role
+ || meth->role == ENDPOINT_BOTH)) {
+ if (idx != NULL)
+ *idx = i;
+ return meth;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Initialise custom extensions flags to indicate neither sent nor received.
+ */
+void custom_ext_init(custom_ext_methods *exts)
+{
+ size_t i;
+ custom_ext_method *meth = exts->meths;
+
+ for (i = 0; i < exts->meths_count; i++, meth++)
+ meth->ext_flags = 0;
+}
+
+/* Pass received custom extension data to the application for parsing. */
+int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
+ const unsigned char *ext_data, size_t ext_size, X509 *x,
+ size_t chainidx)
+{
+ int al;
+ custom_ext_methods *exts = &s->cert->custext;
+ custom_ext_method *meth;
+ ENDPOINT role = ENDPOINT_BOTH;
+
+ if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0)
+ role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT;
+
+ meth = custom_ext_find(exts, role, ext_type, NULL);
+ /* If not found return success */
+ if (!meth)
+ return 1;
+
+ /* Check if extension is defined for our protocol. If not, skip */
+ if (!extension_is_relevant(s, meth->context, context))
+ return 1;
+
+ if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_SERVER_HELLO
+ | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
+ /*
+ * If it's ServerHello or EncryptedExtensions we can't have any
+ * extensions not sent in ClientHello.
+ */
+ if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
+ SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ }
+
+ /*
+ * Extensions received in the ClientHello are marked with the
+ * SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
+ * extensions in the ServerHello/EncryptedExtensions message
+ */
+ if ((context & SSL_EXT_CLIENT_HELLO) != 0)
+ meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;
+
+ /* If no parse function set return success */
+ if (!meth->parse_cb)
+ return 1;
+
+ if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
+ &al, meth->parse_arg) <= 0) {
+ SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Request custom extension data from the application and add to the return
+ * buffer.
+ */
+int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
+ int maxversion)
+{
+ custom_ext_methods *exts = &s->cert->custext;
+ custom_ext_method *meth;
+ size_t i;
+ int al;
+
+ for (i = 0; i < exts->meths_count; i++) {
+ const unsigned char *out = NULL;
+ size_t outlen = 0;
+
+ meth = exts->meths + i;
+
+ if (!should_add_extension(s, meth->context, context, maxversion))
+ continue;
+
+ if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_SERVER_HELLO
+ | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+ | SSL_EXT_TLS1_3_CERTIFICATE
+ | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
+ /* Only send extensions present in ClientHello. */
+ if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
+ continue;
+ }
+ /*
+ * We skip it if the callback is absent - except for a ClientHello where
+ * we add an empty extension.
+ */
+ if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL)
+ continue;
+
+ if (meth->add_cb != NULL) {
+ int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
+ &outlen, x, chainidx, &al,
+ meth->add_arg);
+
+ if (cb_retval < 0) {
+ SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED);
+ return 0; /* error */
+ }
+ if (cb_retval == 0)
+ continue; /* skip this extension */
+ }
+
+ if (!WPACKET_put_bytes_u16(pkt, meth->ext_type)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
+ /*
+ * We can't send duplicates: code logic should prevent this.
+ */
+ if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ /*
+ * Indicate extension has been sent: this is both a sanity check to
+ * ensure we don't send duplicate extensions and indicates that it
+ * is not an error if the extension is present in ServerHello.
+ */
+ meth->ext_flags |= SSL_EXT_FLAG_SENT;
+ }
+ if (meth->free_cb != NULL)
+ meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
+ }
+ return 1;
+}
+
+/* Copy the flags from src to dst for any extensions that exist in both */
+int custom_exts_copy_flags(custom_ext_methods *dst,
+ const custom_ext_methods *src)
+{
+ size_t i;
+ custom_ext_method *methsrc = src->meths;
+
+ for (i = 0; i < src->meths_count; i++, methsrc++) {
+ custom_ext_method *methdst = custom_ext_find(dst, methsrc->role,
+ methsrc->ext_type, NULL);
+
+ if (methdst == NULL)
+ continue;
+
+ methdst->ext_flags = methsrc->ext_flags;
+ }
+
+ return 1;
+}
+
+/* Copy table of custom extensions */
+int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
+{
+ size_t i;
+ int err = 0;
+
+ if (src->meths_count > 0) {
+ dst->meths =
+ OPENSSL_memdup(src->meths,
+ sizeof(*src->meths) * src->meths_count);
+ if (dst->meths == NULL)
+ return 0;
+ dst->meths_count = src->meths_count;
+
+ for (i = 0; i < src->meths_count; i++) {
+ custom_ext_method *methsrc = src->meths + i;
+ custom_ext_method *methdst = dst->meths + i;
+
+ if (methsrc->add_cb != custom_ext_add_old_cb_wrap)
+ continue;
+
+ /*
+ * We have found an old style API wrapper. We need to copy the
+ * arguments too.
+ */
+
+ if (err) {
+ methdst->add_arg = NULL;
+ methdst->parse_arg = NULL;
+ continue;
+ }
+
+ methdst->add_arg = OPENSSL_memdup(methsrc->add_arg,
+ sizeof(custom_ext_add_cb_wrap));
+ methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg,
+ sizeof(custom_ext_parse_cb_wrap));
+
+ if (methdst->add_arg == NULL || methdst->parse_arg == NULL)
+ err = 1;
+ }
+ }
+
+ if (err) {
+ custom_exts_free(dst);
+ return 0;
+ }
+
+ return 1;
+}
+
+void custom_exts_free(custom_ext_methods *exts)
+{
+ size_t i;
+ custom_ext_method *meth;
+
+ for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) {
+ if (meth->add_cb != custom_ext_add_old_cb_wrap)
+ continue;
+
+ /* Old style API wrapper. Need to free the arguments too */
+ OPENSSL_free(meth->add_arg);
+ OPENSSL_free(meth->parse_arg);
+ }
+ OPENSSL_free(exts->meths);
+}
+
+/* Return true if a client custom extension exists, false otherwise */
+int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
+{
+ return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type,
+ NULL) != NULL;
+}
+
+static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role,
+ unsigned int ext_type,
+ unsigned int context,
+ SSL_custom_ext_add_cb_ex add_cb,
+ SSL_custom_ext_free_cb_ex free_cb,
+ void *add_arg,
+ SSL_custom_ext_parse_cb_ex parse_cb,
+ void *parse_arg)
+{
+ custom_ext_methods *exts = &ctx->cert->custext;
+ custom_ext_method *meth, *tmp;
+
+ /*
+ * Check application error: if add_cb is not set free_cb will never be
+ * called.
+ */
+ if (add_cb == NULL && free_cb != NULL)
+ return 0;
+
+#ifndef OPENSSL_NO_CT
+ /*
+ * We don't want applications registering callbacks for SCT extensions
+ * whilst simultaneously using the built-in SCT validation features, as
+ * these two things may not play well together.
+ */
+ if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp
+ && (context & SSL_EXT_CLIENT_HELLO) != 0
+ && SSL_CTX_ct_is_enabled(ctx))
+ return 0;
+#endif
+
+ /*
+ * Don't add if extension supported internally, but make exception
+ * for extension types that previously were not supported, but now are.
+ */
+ if (SSL_extension_supported(ext_type)
+ && ext_type != TLSEXT_TYPE_signed_certificate_timestamp)
+ return 0;
+
+ /* Extension type must fit in 16 bits */
+ if (ext_type > 0xffff)
+ return 0;
+ /* Search for duplicate */
+ if (custom_ext_find(exts, role, ext_type, NULL))
+ return 0;
+ tmp = OPENSSL_realloc(exts->meths,
+ (exts->meths_count + 1) * sizeof(custom_ext_method));
+ if (tmp == NULL)
+ return 0;
+
+ exts->meths = tmp;
+ meth = exts->meths + exts->meths_count;
+ memset(meth, 0, sizeof(*meth));
+ meth->role = role;
+ meth->context = context;
+ meth->parse_cb = parse_cb;
+ meth->add_cb = add_cb;
+ meth->free_cb = free_cb;
+ meth->ext_type = ext_type;
+ meth->add_arg = add_arg;
+ meth->parse_arg = parse_arg;
+ exts->meths_count++;
+ return 1;
+}
+
+static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role,
+ unsigned int ext_type,
+ unsigned int context,
+ custom_ext_add_cb add_cb,
+ custom_ext_free_cb free_cb,
+ void *add_arg,
+ custom_ext_parse_cb parse_cb, void *parse_arg)
+{
+ custom_ext_add_cb_wrap *add_cb_wrap
+ = OPENSSL_malloc(sizeof(*add_cb_wrap));
+ custom_ext_parse_cb_wrap *parse_cb_wrap
+ = OPENSSL_malloc(sizeof(*parse_cb_wrap));
+ int ret;
+
+ if (add_cb_wrap == NULL || parse_cb_wrap == NULL) {
+ OPENSSL_free(add_cb_wrap);
+ OPENSSL_free(parse_cb_wrap);
+ return 0;
+ }
+
+ add_cb_wrap->add_arg = add_arg;
+ add_cb_wrap->add_cb = add_cb;
+ add_cb_wrap->free_cb = free_cb;
+ parse_cb_wrap->parse_arg = parse_arg;
+ parse_cb_wrap->parse_cb = parse_cb;
+
+ ret = add_custom_ext_intern(ctx, role, ext_type,
+ context,
+ custom_ext_add_old_cb_wrap,
+ custom_ext_free_old_cb_wrap,
+ add_cb_wrap,
+ custom_ext_parse_old_cb_wrap,
+ parse_cb_wrap);
+
+ if (!ret) {
+ OPENSSL_free(add_cb_wrap);
+ OPENSSL_free(parse_cb_wrap);
+ }
+
+ return ret;
+}
+
+/* Application level functions to add the old custom extension callbacks */
+int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
+ custom_ext_add_cb add_cb,
+ custom_ext_free_cb free_cb,
+ void *add_arg,
+ custom_ext_parse_cb parse_cb, void *parse_arg)
+{
+ return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type,
+ SSL_EXT_TLS1_2_AND_BELOW_ONLY
+ | SSL_EXT_CLIENT_HELLO
+ | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_IGNORE_ON_RESUMPTION,
+ add_cb, free_cb, add_arg, parse_cb, parse_arg);
+}
+
+int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
+ custom_ext_add_cb add_cb,
+ custom_ext_free_cb free_cb,
+ void *add_arg,
+ custom_ext_parse_cb parse_cb, void *parse_arg)
+{
+ return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type,
+ SSL_EXT_TLS1_2_AND_BELOW_ONLY
+ | SSL_EXT_CLIENT_HELLO
+ | SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_IGNORE_ON_RESUMPTION,
+ add_cb, free_cb, add_arg, parse_cb, parse_arg);
+}
+
+int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
+ unsigned int context,
+ SSL_custom_ext_add_cb_ex add_cb,
+ SSL_custom_ext_free_cb_ex free_cb,
+ void *add_arg,
+ SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg)
+{
+ return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb,
+ free_cb, add_arg, parse_cb, parse_arg);
+}
+
+int SSL_extension_supported(unsigned int ext_type)
+{
+ switch (ext_type) {
+ /* Internally supported extensions. */
+ case TLSEXT_TYPE_application_layer_protocol_negotiation:
+#ifndef OPENSSL_NO_EC
+ case TLSEXT_TYPE_ec_point_formats:
+ case TLSEXT_TYPE_supported_groups:
+ case TLSEXT_TYPE_key_share:
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ case TLSEXT_TYPE_next_proto_neg:
+#endif
+ case TLSEXT_TYPE_padding:
+ case TLSEXT_TYPE_renegotiate:
+ case TLSEXT_TYPE_max_fragment_length:
+ case TLSEXT_TYPE_server_name:
+ case TLSEXT_TYPE_session_ticket:
+ case TLSEXT_TYPE_signature_algorithms:
+#ifndef OPENSSL_NO_SRP
+ case TLSEXT_TYPE_srp:
+#endif
+#ifndef OPENSSL_NO_OCSP
+ case TLSEXT_TYPE_status_request:
+#endif
+#ifndef OPENSSL_NO_CT
+ case TLSEXT_TYPE_signed_certificate_timestamp:
+#endif
+#ifndef OPENSSL_NO_SRTP
+ case TLSEXT_TYPE_use_srtp:
+#endif
+ case TLSEXT_TYPE_encrypt_then_mac:
+ case TLSEXT_TYPE_supported_versions:
+ case TLSEXT_TYPE_extended_master_secret:
+ case TLSEXT_TYPE_psk_kex_modes:
+ case TLSEXT_TYPE_cookie:
+ case TLSEXT_TYPE_early_data:
+ case TLSEXT_TYPE_certificate_authorities:
+ case TLSEXT_TYPE_psk:
+ case TLSEXT_TYPE_post_handshake_auth:
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/contrib/libs/openssl/ssl/statem/extensions_srvr.c b/contrib/libs/openssl/ssl/statem/extensions_srvr.c
index 04f64f8106..73e509e457 100644
--- a/contrib/libs/openssl/ssl/statem/extensions_srvr.c
+++ b/contrib/libs/openssl/ssl/statem/extensions_srvr.c
@@ -1,1343 +1,1343 @@
-/*
+/*
* Copyright 2016-2021 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 <openssl/ocsp.h>
+ *
+ * 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 <openssl/ocsp.h>
#include "../ssl_local.h"
#include "statem_local.h"
-#include "internal/cryptlib.h"
-
-#define COOKIE_STATE_FORMAT_VERSION 0
-
-/*
- * 2 bytes for packet length, 2 bytes for format version, 2 bytes for
- * protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for
- * key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen,
- * EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie
- * length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing.
- */
-#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \
- + SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH)
-
-/*
- * Message header + 2 bytes for protocol version + number of random bytes +
- * + 1 byte for legacy session id length + number of bytes in legacy session id
- * + 2 bytes for ciphersuite + 1 byte for legacy compression
- * + 2 bytes for extension block length + 6 bytes for key_share extension
- * + 4 bytes for cookie extension header + the number of bytes in the cookie
- */
-#define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \
- + SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \
- + MAX_COOKIE_SIZE)
-
-/*
- * Parse the client's renegotiation binding and abort if it's not right
- */
-int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- unsigned int ilen;
- const unsigned char *data;
-
- /* Parse the length byte */
- if (!PACKET_get_1(pkt, &ilen)
- || !PACKET_get_bytes(pkt, &data, ilen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
- SSL_R_RENEGOTIATION_ENCODING_ERR);
- return 0;
- }
-
- /* Check that the extension matches */
- if (ilen != s->s3->previous_client_finished_len) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
- return 0;
- }
-
- if (memcmp(data, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
- SSL_R_RENEGOTIATION_MISMATCH);
- return 0;
- }
-
- s->s3->send_connection_binding = 1;
-
- return 1;
-}
-
-/*-
- * 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.
- */
-int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- unsigned int servname_type;
- PACKET sni, hostname;
-
- if (!PACKET_as_length_prefixed_2(pkt, &sni)
- /* ServerNameList must be at least 1 byte long. */
- || PACKET_remaining(&sni) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- /*
- * Although the intent was for server_name to be extensible, RFC 4366
- * was not clear about it; and so OpenSSL among other implementations,
- * always and only allows a 'host_name' name types.
- * 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)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
+#include "internal/cryptlib.h"
+
+#define COOKIE_STATE_FORMAT_VERSION 0
+
+/*
+ * 2 bytes for packet length, 2 bytes for format version, 2 bytes for
+ * protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for
+ * key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen,
+ * EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie
+ * length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing.
+ */
+#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \
+ + SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH)
+
+/*
+ * Message header + 2 bytes for protocol version + number of random bytes +
+ * + 1 byte for legacy session id length + number of bytes in legacy session id
+ * + 2 bytes for ciphersuite + 1 byte for legacy compression
+ * + 2 bytes for extension block length + 6 bytes for key_share extension
+ * + 4 bytes for cookie extension header + the number of bytes in the cookie
+ */
+#define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \
+ + SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \
+ + MAX_COOKIE_SIZE)
+
+/*
+ * Parse the client's renegotiation binding and abort if it's not right
+ */
+int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ unsigned int ilen;
+ const unsigned char *data;
+
+ /* Parse the length byte */
+ if (!PACKET_get_1(pkt, &ilen)
+ || !PACKET_get_bytes(pkt, &data, ilen)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_ENCODING_ERR);
+ return 0;
+ }
+
+ /* Check that the extension matches */
+ if (ilen != s->s3->previous_client_finished_len) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ return 0;
+ }
+
+ if (memcmp(data, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
+ SSL_R_RENEGOTIATION_MISMATCH);
+ return 0;
+ }
+
+ s->s3->send_connection_binding = 1;
+
+ return 1;
+}
+
+/*-
+ * 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.
+ */
+int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ unsigned int servname_type;
+ PACKET sni, hostname;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &sni)
+ /* ServerNameList must be at least 1 byte long. */
+ || PACKET_remaining(&sni) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ /*
+ * Although the intent was for server_name to be extensible, RFC 4366
+ * was not clear about it; and so OpenSSL among other implementations,
+ * always and only allows a 'host_name' name types.
+ * 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)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
/*
* In TLSv1.2 and below the SNI is associated with the session. In TLSv1.3
* we always use the SNI value from the handshake.
*/
- if (!s->hit || SSL_IS_TLS13(s)) {
- if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
- SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
- SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (PACKET_contains_zero_byte(&hostname)) {
- SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
- SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- /*
- * Store the requested SNI in the SSL as temporary storage.
- * If we accept it, it will get stored in the SSL_SESSION as well.
- */
- OPENSSL_free(s->ext.hostname);
- s->ext.hostname = NULL;
- if (!PACKET_strndup(&hostname, &s->ext.hostname)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- s->servername_done = 1;
+ if (!s->hit || SSL_IS_TLS13(s)) {
+ if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
+ SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
+ SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (PACKET_contains_zero_byte(&hostname)) {
+ SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
+ SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ /*
+ * Store the requested SNI in the SSL as temporary storage.
+ * If we accept it, it will get stored in the SSL_SESSION as well.
+ */
+ OPENSSL_free(s->ext.hostname);
+ s->ext.hostname = NULL;
+ if (!PACKET_strndup(&hostname, &s->ext.hostname)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ s->servername_done = 1;
} else {
- /*
+ /*
* In TLSv1.2 and below we should check if the SNI is consistent between
* the initial handshake and the resumption. In TLSv1.3 SNI is not
* associated with the session.
*/
/*
- * TODO(openssl-team): if the SNI doesn't match, we MUST
- * fall back to a full handshake.
- */
- s->servername_done = (s->session->ext.hostname != NULL)
- && PACKET_equal(&hostname, s->session->ext.hostname,
- strlen(s->session->ext.hostname));
- }
-
- return 1;
-}
-
-int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- unsigned int value;
-
- if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- /* Received |value| should be a valid max-fragment-length code. */
- if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
- SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
- return 0;
- }
-
- /*
- * RFC 6066: The negotiated length applies for the duration of the session
- * including session resumptions.
- * We should receive the same code as in resumed session !
- */
- if (s->hit && s->session->ext.max_fragment_len_mode != value) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
- SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
- return 0;
- }
-
- /*
- * Store it in session, so it'll become binding for us
- * and we'll include it in a next Server Hello.
- */
- s->session->ext.max_fragment_len_mode = value;
- return 1;
-}
-
-#ifndef OPENSSL_NO_SRP
-int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- PACKET srp_I;
-
- if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
- || PACKET_contains_zero_byte(&srp_I)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SRP,
- SSL_R_BAD_EXTENSION);
- 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)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-#endif
-
-#ifndef OPENSSL_NO_EC
-int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- PACKET ec_point_format_list;
-
- if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
- || PACKET_remaining(&ec_point_format_list) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!s->hit) {
- if (!PACKET_memdup(&ec_point_format_list,
+ * TODO(openssl-team): if the SNI doesn't match, we MUST
+ * fall back to a full handshake.
+ */
+ s->servername_done = (s->session->ext.hostname != NULL)
+ && PACKET_equal(&hostname, s->session->ext.hostname,
+ strlen(s->session->ext.hostname));
+ }
+
+ return 1;
+}
+
+int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ unsigned int value;
+
+ if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ /* Received |value| should be a valid max-fragment-length code. */
+ if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
+ SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+
+ /*
+ * RFC 6066: The negotiated length applies for the duration of the session
+ * including session resumptions.
+ * We should receive the same code as in resumed session !
+ */
+ if (s->hit && s->session->ext.max_fragment_len_mode != value) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
+ SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+
+ /*
+ * Store it in session, so it'll become binding for us
+ * and we'll include it in a next Server Hello.
+ */
+ s->session->ext.max_fragment_len_mode = value;
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRP
+int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ PACKET srp_I;
+
+ if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
+ || PACKET_contains_zero_byte(&srp_I)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SRP,
+ SSL_R_BAD_EXTENSION);
+ 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)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ PACKET ec_point_format_list;
+
+ if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
+ || PACKET_remaining(&ec_point_format_list) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!s->hit) {
+ if (!PACKET_memdup(&ec_point_format_list,
&s->ext.peer_ecpointformats,
&s->ext.peer_ecpointformats_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- return 1;
-}
-#endif /* OPENSSL_NO_EC */
-
-int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (s->ext.session_ticket_cb &&
- !s->ext.session_ticket_cb(s, PACKET_data(pkt),
- PACKET_remaining(pkt),
- s->ext.session_ticket_cb_arg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- PACKET supported_sig_algs;
-
- if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
- || PACKET_remaining(&supported_sig_algs) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- return 1;
-}
-
-int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- PACKET supported_sig_algs;
-
- if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
- || PACKET_remaining(&supported_sig_algs) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_OCSP
-int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- PACKET responder_id_list, exts;
-
- /* We ignore this in a resumption handshake */
- if (s->hit)
- return 1;
-
- /* Not defined if we get one of these in a client Certificate */
- if (x != NULL)
- return 1;
-
- if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
- /*
- * We don't know what to do with any other type so ignore it.
- */
- s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
- return 1;
- }
-
- if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- 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->ext.ocsp.ids, OCSP_RESPID_free);
- if (PACKET_remaining(&responder_id_list) > 0) {
- s->ext.ocsp.ids = sk_OCSP_RESPID_new_null();
- if (s->ext.ocsp.ids == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- } else {
- s->ext.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) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- 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) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (id_data != PACKET_end(&responder_id)) {
- OCSP_RESPID_free(id);
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
-
- return 0;
- }
-
- if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) {
- OCSP_RESPID_free(id);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
-
- return 0;
- }
- }
-
- /* Read in request_extensions */
- if (!PACKET_as_length_prefixed_2(pkt, &exts)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (PACKET_remaining(&exts) > 0) {
- const unsigned char *ext_data = PACKET_data(&exts);
-
- sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts,
- X509_EXTENSION_free);
- s->ext.ocsp.exts =
- d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts));
- if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
- return 0;
- }
- }
-
- return 1;
-}
-#endif
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
-int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- /*
- * We shouldn't accept this extension on a
- * renegotiation.
- */
- if (SSL_IS_FIRST_HANDSHAKE(s))
- s->s3->npn_seen = 1;
-
- return 1;
-}
-#endif
-
-/*
- * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN
- * extension, not including type and length. Returns: 1 on success, 0 on error.
- */
-int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- PACKET protocol_list, save_protocol_list, protocol;
-
- if (!SSL_IS_FIRST_HANDSHAKE(s))
- return 1;
-
- if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
- || PACKET_remaining(&protocol_list) < 2) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
- SSL_R_BAD_EXTENSION);
- 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) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
- } while (PACKET_remaining(&protocol_list) != 0);
-
- OPENSSL_free(s->s3->alpn_proposed);
- s->s3->alpn_proposed = NULL;
- s->s3->alpn_proposed_len = 0;
- if (!PACKET_memdup(&save_protocol_list,
- &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_SRTP
-int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- 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)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- 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)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- 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++) {
- SRTP_PROTECTION_PROFILE *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)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- return 0;
- }
-
- if (!PACKET_forward(pkt, mki_len)
- || PACKET_remaining(pkt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
- SSL_R_BAD_SRTP_MKI_VALUE);
- return 0;
- }
-
- return 1;
-}
-#endif
-
-int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
- s->ext.use_etm = 1;
-
- return 1;
-}
-
-/*
- * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains
- * the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
- */
-int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- PACKET psk_kex_modes;
- unsigned int mode;
-
- if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes)
- || PACKET_remaining(&psk_kex_modes) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- while (PACKET_get_1(&psk_kex_modes, &mode)) {
- if (mode == TLSEXT_KEX_MODE_KE_DHE)
- s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE;
- else if (mode == TLSEXT_KEX_MODE_KE
- && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0)
- s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
- }
-#endif
-
- return 1;
-}
-
-/*
- * 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.
- */
-int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- unsigned int group_id;
- PACKET key_share_list, encoded_pt;
- const uint16_t *clntgroups, *srvrgroups;
- size_t clnt_num_groups, srvr_num_groups;
- int found = 0;
-
- if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0)
- return 1;
-
- /* Sanity check */
- if (s->s3->peer_tmp != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- /* Get our list of supported groups */
- tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups);
- /* Get the clients list of supported groups. */
- tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
- if (clnt_num_groups == 0) {
- /*
- * This can only happen if the supported_groups extension was not sent,
- * because we verify that the length is non-zero when we process that
- * extension.
- */
- SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
- return 0;
- }
-
- if (s->s3->group_id != 0 && PACKET_remaining(&key_share_list) == 0) {
- /*
- * If we set a group_id already, then we must have sent an HRR
- * requesting a new key_share. If we haven't got one then that is an
- * error
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- SSL_R_BAD_KEY_SHARE);
- 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) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_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;
-
- /*
- * If we sent an HRR then the key_share sent back MUST be for the group
- * we requested, and must be the only key_share sent.
- */
- if (s->s3->group_id != 0
- && (group_id != s->s3->group_id
- || PACKET_remaining(&key_share_list) != 0)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
- return 0;
- }
-
- /* Check if this share is in supported_groups sent from client */
- if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_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, srvrgroups, srvr_num_groups, 1)) {
- /* Share not suitable */
- continue;
- }
-
- if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
- SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
- return 0;
- }
-
- s->s3->group_id = group_id;
-
- if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
- PACKET_data(&encoded_pt),
- PACKET_remaining(&encoded_pt))) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
- return 0;
- }
-
- found = 1;
- }
-#endif
-
- return 1;
-}
-
-int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- unsigned int format, version, key_share, group_id;
- EVP_MD_CTX *hctx;
- EVP_PKEY *pkey;
- PACKET cookie, raw, chhash, appcookie;
- WPACKET hrrpkt;
- const unsigned char *data, *mdin, *ciphdata;
- unsigned char hmac[SHA256_DIGEST_LENGTH];
- unsigned char hrr[MAX_HRR_SIZE];
- size_t rawlen, hmaclen, hrrlen, ciphlen;
- unsigned long tm, now;
-
- /* Ignore any cookie if we're not set up to verify it */
- if (s->ctx->verify_stateless_cookie_cb == NULL
- || (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
- return 1;
-
- if (!PACKET_as_length_prefixed_2(pkt, &cookie)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- raw = cookie;
- data = PACKET_data(&raw);
- rawlen = PACKET_remaining(&raw);
- if (rawlen < SHA256_DIGEST_LENGTH
- || !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
- mdin = PACKET_data(&raw);
-
- /* Verify the HMAC of the cookie */
- hctx = EVP_MD_CTX_create();
- pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
- s->session_ctx->ext.cookie_hmac_key,
- sizeof(s->session_ctx->ext
- .cookie_hmac_key));
- if (hctx == NULL || pkey == NULL) {
- EVP_MD_CTX_free(hctx);
- EVP_PKEY_free(pkey);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- hmaclen = SHA256_DIGEST_LENGTH;
- if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
- || EVP_DigestSign(hctx, hmac, &hmaclen, data,
- rawlen - SHA256_DIGEST_LENGTH) <= 0
- || hmaclen != SHA256_DIGEST_LENGTH) {
- EVP_MD_CTX_free(hctx);
- EVP_PKEY_free(pkey);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- EVP_MD_CTX_free(hctx);
- EVP_PKEY_free(pkey);
-
- if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_COOKIE_MISMATCH);
- return 0;
- }
-
- if (!PACKET_get_net_2(&cookie, &format)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
- /* Check the cookie format is something we recognise. Ignore it if not */
- if (format != COOKIE_STATE_FORMAT_VERSION)
- return 1;
-
- /*
- * The rest of these checks really shouldn't fail since we have verified the
- * HMAC above.
- */
-
- /* Check the version number is sane */
- if (!PACKET_get_net_2(&cookie, &version)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
- if (version != TLS1_3_VERSION) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
- return 0;
- }
-
- if (!PACKET_get_net_2(&cookie, &group_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- ciphdata = PACKET_data(&cookie);
- if (!PACKET_forward(&cookie, 2)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
- if (group_id != s->s3->group_id
- || s->s3->tmp.new_cipher
- != ssl_get_cipher_by_char(s, ciphdata, 0)) {
- /*
- * We chose a different cipher or group id this time around to what is
- * in the cookie. Something must have changed.
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_BAD_CIPHER);
- return 0;
- }
-
- if (!PACKET_get_1(&cookie, &key_share)
- || !PACKET_get_net_4(&cookie, &tm)
- || !PACKET_get_length_prefixed_2(&cookie, &chhash)
- || !PACKET_get_length_prefixed_1(&cookie, &appcookie)
- || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */
- now = (unsigned long)time(NULL);
- if (tm > now || (now - tm) > 600) {
- /* Cookie is stale. Ignore it */
- return 1;
- }
-
- /* Verify the app cookie */
- if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie),
- PACKET_remaining(&appcookie)) == 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
- SSL_R_COOKIE_MISMATCH);
- return 0;
- }
-
- /*
- * Reconstruct the HRR that we would have sent in response to the original
- * ClientHello so we can add it to the transcript hash.
- * Note: This won't work with custom HRR extensions
- */
- if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO)
- || !WPACKET_start_sub_packet_u24(&hrrpkt)
- || !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION)
- || !WPACKET_memcpy(&hrrpkt, hrrrandom, SSL3_RANDOM_SIZE)
- || !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id,
- s->tmp_session_id_len)
- || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &hrrpkt,
- &ciphlen)
- || !WPACKET_put_bytes_u8(&hrrpkt, 0)
- || !WPACKET_start_sub_packet_u16(&hrrpkt)) {
- WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions)
- || !WPACKET_start_sub_packet_u16(&hrrpkt)
- || !WPACKET_put_bytes_u16(&hrrpkt, s->version)
- || !WPACKET_close(&hrrpkt)) {
- WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (key_share) {
- if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share)
- || !WPACKET_start_sub_packet_u16(&hrrpkt)
- || !WPACKET_put_bytes_u16(&hrrpkt, s->s3->group_id)
- || !WPACKET_close(&hrrpkt)) {
- WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie)
- || !WPACKET_start_sub_packet_u16(&hrrpkt)
- || !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen)
- || !WPACKET_close(&hrrpkt) /* cookie extension */
- || !WPACKET_close(&hrrpkt) /* extension block */
- || !WPACKET_close(&hrrpkt) /* message */
- || !WPACKET_get_total_written(&hrrpkt, &hrrlen)
- || !WPACKET_finish(&hrrpkt)) {
- WPACKET_cleanup(&hrrpkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* Reconstruct the transcript hash */
- if (!create_synthetic_message_hash(s, PACKET_data(&chhash),
- PACKET_remaining(&chhash), hrr,
- hrrlen)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /* Act as if this ClientHello came after a HelloRetryRequest */
- s->hello_retry_request = 1;
-
- s->ext.cookieok = 1;
-#endif
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_EC
-int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- 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) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (!s->hit || SSL_IS_TLS13(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif /* OPENSSL_NO_EC */
+
+int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (s->ext.session_ticket_cb &&
+ !s->ext.session_ticket_cb(s, PACKET_data(pkt),
+ PACKET_remaining(pkt),
+ s->ext.session_ticket_cb_arg)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ PACKET supported_sig_algs;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
+ || PACKET_remaining(&supported_sig_algs) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ PACKET supported_sig_algs;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
+ || PACKET_remaining(&supported_sig_algs) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_OCSP
+int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ PACKET responder_id_list, exts;
+
+ /* We ignore this in a resumption handshake */
+ if (s->hit)
+ return 1;
+
+ /* Not defined if we get one of these in a client Certificate */
+ if (x != NULL)
+ return 1;
+
+ if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
+ /*
+ * We don't know what to do with any other type so ignore it.
+ */
+ s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
+ return 1;
+ }
+
+ if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ 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->ext.ocsp.ids, OCSP_RESPID_free);
+ if (PACKET_remaining(&responder_id_list) > 0) {
+ s->ext.ocsp.ids = sk_OCSP_RESPID_new_null();
+ if (s->ext.ocsp.ids == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else {
+ s->ext.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) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ 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) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (id_data != PACKET_end(&responder_id)) {
+ OCSP_RESPID_free(id);
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+
+ return 0;
+ }
+
+ if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) {
+ OCSP_RESPID_free(id);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+
+ return 0;
+ }
+ }
+
+ /* Read in request_extensions */
+ if (!PACKET_as_length_prefixed_2(pkt, &exts)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (PACKET_remaining(&exts) > 0) {
+ const unsigned char *ext_data = PACKET_data(&exts);
+
+ sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts,
+ X509_EXTENSION_free);
+ s->ext.ocsp.exts =
+ d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts));
+ if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ /*
+ * We shouldn't accept this extension on a
+ * renegotiation.
+ */
+ if (SSL_IS_FIRST_HANDSHAKE(s))
+ s->s3->npn_seen = 1;
+
+ return 1;
+}
+#endif
+
+/*
+ * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN
+ * extension, not including type and length. Returns: 1 on success, 0 on error.
+ */
+int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ PACKET protocol_list, save_protocol_list, protocol;
+
+ if (!SSL_IS_FIRST_HANDSHAKE(s))
+ return 1;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
+ || PACKET_remaining(&protocol_list) < 2) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
+ SSL_R_BAD_EXTENSION);
+ 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) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+ } while (PACKET_remaining(&protocol_list) != 0);
+
+ OPENSSL_free(s->s3->alpn_proposed);
+ s->s3->alpn_proposed = NULL;
+ s->s3->alpn_proposed_len = 0;
+ if (!PACKET_memdup(&save_protocol_list,
+ &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRTP
+int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ 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)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ 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)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ 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++) {
+ SRTP_PROTECTION_PROFILE *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)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ return 0;
+ }
+
+ if (!PACKET_forward(pkt, mki_len)
+ || PACKET_remaining(pkt)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+ SSL_R_BAD_SRTP_MKI_VALUE);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
+ s->ext.use_etm = 1;
+
+ return 1;
+}
+
+/*
+ * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains
+ * the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
+ */
+int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ PACKET psk_kex_modes;
+ unsigned int mode;
+
+ if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes)
+ || PACKET_remaining(&psk_kex_modes) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ while (PACKET_get_1(&psk_kex_modes, &mode)) {
+ if (mode == TLSEXT_KEX_MODE_KE_DHE)
+ s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE;
+ else if (mode == TLSEXT_KEX_MODE_KE
+ && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0)
+ s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
+ }
+#endif
+
+ return 1;
+}
+
+/*
+ * 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.
+ */
+int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ unsigned int group_id;
+ PACKET key_share_list, encoded_pt;
+ const uint16_t *clntgroups, *srvrgroups;
+ size_t clnt_num_groups, srvr_num_groups;
+ int found = 0;
+
+ if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0)
+ return 1;
+
+ /* Sanity check */
+ if (s->s3->peer_tmp != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /* Get our list of supported groups */
+ tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups);
+ /* Get the clients list of supported groups. */
+ tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
+ if (clnt_num_groups == 0) {
+ /*
+ * This can only happen if the supported_groups extension was not sent,
+ * because we verify that the length is non-zero when we process that
+ * extension.
+ */
+ SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+ SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
+ return 0;
+ }
+
+ if (s->s3->group_id != 0 && PACKET_remaining(&key_share_list) == 0) {
+ /*
+ * If we set a group_id already, then we must have sent an HRR
+ * requesting a new key_share. If we haven't got one then that is an
+ * error
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+ SSL_R_BAD_KEY_SHARE);
+ 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) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_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;
+
+ /*
+ * If we sent an HRR then the key_share sent back MUST be for the group
+ * we requested, and must be the only key_share sent.
+ */
+ if (s->s3->group_id != 0
+ && (group_id != s->s3->group_id
+ || PACKET_remaining(&key_share_list) != 0)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+ return 0;
+ }
+
+ /* Check if this share is in supported_groups sent from client */
+ if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_CTOS_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, srvrgroups, srvr_num_groups, 1)) {
+ /* Share not suitable */
+ continue;
+ }
+
+ if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+ SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+ return 0;
+ }
+
+ s->s3->group_id = group_id;
+
+ if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
+ PACKET_data(&encoded_pt),
+ PACKET_remaining(&encoded_pt))) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
+ return 0;
+ }
+
+ found = 1;
+ }
+#endif
+
+ return 1;
+}
+
+int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ unsigned int format, version, key_share, group_id;
+ EVP_MD_CTX *hctx;
+ EVP_PKEY *pkey;
+ PACKET cookie, raw, chhash, appcookie;
+ WPACKET hrrpkt;
+ const unsigned char *data, *mdin, *ciphdata;
+ unsigned char hmac[SHA256_DIGEST_LENGTH];
+ unsigned char hrr[MAX_HRR_SIZE];
+ size_t rawlen, hmaclen, hrrlen, ciphlen;
+ unsigned long tm, now;
+
+ /* Ignore any cookie if we're not set up to verify it */
+ if (s->ctx->verify_stateless_cookie_cb == NULL
+ || (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
+ return 1;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &cookie)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ raw = cookie;
+ data = PACKET_data(&raw);
+ rawlen = PACKET_remaining(&raw);
+ if (rawlen < SHA256_DIGEST_LENGTH
+ || !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ mdin = PACKET_data(&raw);
+
+ /* Verify the HMAC of the cookie */
+ hctx = EVP_MD_CTX_create();
+ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
+ s->session_ctx->ext.cookie_hmac_key,
+ sizeof(s->session_ctx->ext
+ .cookie_hmac_key));
+ if (hctx == NULL || pkey == NULL) {
+ EVP_MD_CTX_free(hctx);
+ EVP_PKEY_free(pkey);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ hmaclen = SHA256_DIGEST_LENGTH;
+ if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
+ || EVP_DigestSign(hctx, hmac, &hmaclen, data,
+ rawlen - SHA256_DIGEST_LENGTH) <= 0
+ || hmaclen != SHA256_DIGEST_LENGTH) {
+ EVP_MD_CTX_free(hctx);
+ EVP_PKEY_free(pkey);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ EVP_MD_CTX_free(hctx);
+ EVP_PKEY_free(pkey);
+
+ if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_COOKIE_MISMATCH);
+ return 0;
+ }
+
+ if (!PACKET_get_net_2(&cookie, &format)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ /* Check the cookie format is something we recognise. Ignore it if not */
+ if (format != COOKIE_STATE_FORMAT_VERSION)
+ return 1;
+
+ /*
+ * The rest of these checks really shouldn't fail since we have verified the
+ * HMAC above.
+ */
+
+ /* Check the version number is sane */
+ if (!PACKET_get_net_2(&cookie, &version)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ if (version != TLS1_3_VERSION) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
+ return 0;
+ }
+
+ if (!PACKET_get_net_2(&cookie, &group_id)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ ciphdata = PACKET_data(&cookie);
+ if (!PACKET_forward(&cookie, 2)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ if (group_id != s->s3->group_id
+ || s->s3->tmp.new_cipher
+ != ssl_get_cipher_by_char(s, ciphdata, 0)) {
+ /*
+ * We chose a different cipher or group id this time around to what is
+ * in the cookie. Something must have changed.
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_BAD_CIPHER);
+ return 0;
+ }
+
+ if (!PACKET_get_1(&cookie, &key_share)
+ || !PACKET_get_net_4(&cookie, &tm)
+ || !PACKET_get_length_prefixed_2(&cookie, &chhash)
+ || !PACKET_get_length_prefixed_1(&cookie, &appcookie)
+ || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */
+ now = (unsigned long)time(NULL);
+ if (tm > now || (now - tm) > 600) {
+ /* Cookie is stale. Ignore it */
+ return 1;
+ }
+
+ /* Verify the app cookie */
+ if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie),
+ PACKET_remaining(&appcookie)) == 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ SSL_R_COOKIE_MISMATCH);
+ return 0;
+ }
+
+ /*
+ * Reconstruct the HRR that we would have sent in response to the original
+ * ClientHello so we can add it to the transcript hash.
+ * Note: This won't work with custom HRR extensions
+ */
+ if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO)
+ || !WPACKET_start_sub_packet_u24(&hrrpkt)
+ || !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION)
+ || !WPACKET_memcpy(&hrrpkt, hrrrandom, SSL3_RANDOM_SIZE)
+ || !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id,
+ s->tmp_session_id_len)
+ || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &hrrpkt,
+ &ciphlen)
+ || !WPACKET_put_bytes_u8(&hrrpkt, 0)
+ || !WPACKET_start_sub_packet_u16(&hrrpkt)) {
+ WPACKET_cleanup(&hrrpkt);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions)
+ || !WPACKET_start_sub_packet_u16(&hrrpkt)
+ || !WPACKET_put_bytes_u16(&hrrpkt, s->version)
+ || !WPACKET_close(&hrrpkt)) {
+ WPACKET_cleanup(&hrrpkt);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (key_share) {
+ if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share)
+ || !WPACKET_start_sub_packet_u16(&hrrpkt)
+ || !WPACKET_put_bytes_u16(&hrrpkt, s->s3->group_id)
+ || !WPACKET_close(&hrrpkt)) {
+ WPACKET_cleanup(&hrrpkt);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie)
+ || !WPACKET_start_sub_packet_u16(&hrrpkt)
+ || !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen)
+ || !WPACKET_close(&hrrpkt) /* cookie extension */
+ || !WPACKET_close(&hrrpkt) /* extension block */
+ || !WPACKET_close(&hrrpkt) /* message */
+ || !WPACKET_get_total_written(&hrrpkt, &hrrlen)
+ || !WPACKET_finish(&hrrpkt)) {
+ WPACKET_cleanup(&hrrpkt);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Reconstruct the transcript hash */
+ if (!create_synthetic_message_hash(s, PACKET_data(&chhash),
+ PACKET_remaining(&chhash), hrr,
+ hrrlen)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ /* Act as if this ClientHello came after a HelloRetryRequest */
+ s->hello_retry_request = 1;
+
+ s->ext.cookieok = 1;
+#endif
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ 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) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (!s->hit || SSL_IS_TLS13(s)) {
OPENSSL_free(s->ext.peer_supportedgroups);
s->ext.peer_supportedgroups = NULL;
s->ext.peer_supportedgroups_len = 0;
- if (!tls1_save_u16(&supported_groups_list,
+ if (!tls1_save_u16(&supported_groups_list,
&s->ext.peer_supportedgroups,
&s->ext.peer_supportedgroups_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- return 1;
-}
-#endif
-
-int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- /* The extension must always be empty */
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
-
- return 1;
-}
-
-
-int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (s->hello_retry_request != SSL_HRR_NONE) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- return 1;
-}
-
-static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
- SSL_SESSION **sess)
-{
- SSL_SESSION *tmpsess = NULL;
-
- s->ext.ticket_expected = 1;
-
- switch (PACKET_remaining(tick)) {
- case 0:
- return SSL_TICKET_EMPTY;
-
- case SSL_MAX_SSL_SESSION_ID_LENGTH:
- break;
-
- default:
- return SSL_TICKET_NO_DECRYPT;
- }
-
- tmpsess = lookup_sess_in_cache(s, PACKET_data(tick),
- SSL_MAX_SSL_SESSION_ID_LENGTH);
-
- if (tmpsess == NULL)
- return SSL_TICKET_NO_DECRYPT;
-
- *sess = tmpsess;
- return SSL_TICKET_SUCCESS;
-}
-
-int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
- size_t chainidx)
-{
- PACKET identities, binders, binder;
- size_t binderoffset, hashsize;
- SSL_SESSION *sess = NULL;
- unsigned int id, i, ext = 0;
- const EVP_MD *md = NULL;
-
- /*
- * If we have no PSK kex mode that we recognise then we can't resume so
- * ignore this extension
- */
- if ((s->ext.psk_kex_mode
- & (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0)
- return 1;
-
- if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- s->ext.ticket_expected = 0;
- for (id = 0; PACKET_remaining(&identities) != 0; id++) {
- PACKET identity;
- unsigned long ticket_agel;
- size_t idlen;
-
- if (!PACKET_get_length_prefixed_2(&identities, &identity)
- || !PACKET_get_net_4(&identities, &ticket_agel)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- idlen = PACKET_remaining(&identity);
- if (s->psk_find_session_cb != NULL
- && !s->psk_find_session_cb(s, PACKET_data(&identity), idlen,
- &sess)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
- return 0;
- }
-
-#ifndef OPENSSL_NO_PSK
- if(sess == NULL
- && s->psk_server_callback != NULL
- && idlen <= PSK_MAX_IDENTITY_LEN) {
- char *pskid = NULL;
- unsigned char pskdata[PSK_MAX_PSK_LEN];
- unsigned int pskdatalen;
-
- if (!PACKET_strndup(&identity, &pskid)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- pskdatalen = s->psk_server_callback(s, pskid, pskdata,
- sizeof(pskdata));
- OPENSSL_free(pskid);
- if (pskdatalen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return 0;
- } else if (pskdatalen > 0) {
- const SSL_CIPHER *cipher;
- const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
-
- /*
- * We found a PSK using an old style callback. We don't know
- * the digest so we default to SHA256 as per the TLSv1.3 spec
- */
- cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
- if (cipher == NULL) {
- OPENSSL_cleanse(pskdata, pskdatalen);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- sess = SSL_SESSION_new();
- if (sess == NULL
- || !SSL_SESSION_set1_master_key(sess, pskdata,
- pskdatalen)
- || !SSL_SESSION_set_cipher(sess, cipher)
- || !SSL_SESSION_set_protocol_version(sess,
- TLS1_3_VERSION)) {
- OPENSSL_cleanse(pskdata, pskdatalen);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- OPENSSL_cleanse(pskdata, pskdatalen);
- }
- }
-#endif /* OPENSSL_NO_PSK */
-
- if (sess != NULL) {
- /* We found a PSK */
- SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
-
- if (sesstmp == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ /* The extension must always be empty */
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
+
+ return 1;
+}
+
+
+int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (s->hello_retry_request != SSL_HRR_NONE) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ return 1;
+}
+
+static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
+ SSL_SESSION **sess)
+{
+ SSL_SESSION *tmpsess = NULL;
+
+ s->ext.ticket_expected = 1;
+
+ switch (PACKET_remaining(tick)) {
+ case 0:
+ return SSL_TICKET_EMPTY;
+
+ case SSL_MAX_SSL_SESSION_ID_LENGTH:
+ break;
+
+ default:
+ return SSL_TICKET_NO_DECRYPT;
+ }
+
+ tmpsess = lookup_sess_in_cache(s, PACKET_data(tick),
+ SSL_MAX_SSL_SESSION_ID_LENGTH);
+
+ if (tmpsess == NULL)
+ return SSL_TICKET_NO_DECRYPT;
+
+ *sess = tmpsess;
+ return SSL_TICKET_SUCCESS;
+}
+
+int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ PACKET identities, binders, binder;
+ size_t binderoffset, hashsize;
+ SSL_SESSION *sess = NULL;
+ unsigned int id, i, ext = 0;
+ const EVP_MD *md = NULL;
+
+ /*
+ * If we have no PSK kex mode that we recognise then we can't resume so
+ * ignore this extension
+ */
+ if ((s->ext.psk_kex_mode
+ & (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0)
+ return 1;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ s->ext.ticket_expected = 0;
+ for (id = 0; PACKET_remaining(&identities) != 0; id++) {
+ PACKET identity;
+ unsigned long ticket_agel;
+ size_t idlen;
+
+ if (!PACKET_get_length_prefixed_2(&identities, &identity)
+ || !PACKET_get_net_4(&identities, &ticket_agel)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ idlen = PACKET_remaining(&identity);
+ if (s->psk_find_session_cb != NULL
+ && !s->psk_find_session_cb(s, PACKET_data(&identity), idlen,
+ &sess)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+#ifndef OPENSSL_NO_PSK
+ if(sess == NULL
+ && s->psk_server_callback != NULL
+ && idlen <= PSK_MAX_IDENTITY_LEN) {
+ char *pskid = NULL;
+ unsigned char pskdata[PSK_MAX_PSK_LEN];
+ unsigned int pskdatalen;
+
+ if (!PACKET_strndup(&identity, &pskid)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ pskdatalen = s->psk_server_callback(s, pskid, pskdata,
+ sizeof(pskdata));
+ OPENSSL_free(pskid);
+ if (pskdatalen > PSK_MAX_PSK_LEN) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ } else if (pskdatalen > 0) {
+ const SSL_CIPHER *cipher;
+ const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
+
+ /*
+ * We found a PSK using an old style callback. We don't know
+ * the digest so we default to SHA256 as per the TLSv1.3 spec
+ */
+ cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
+ if (cipher == NULL) {
+ OPENSSL_cleanse(pskdata, pskdatalen);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ sess = SSL_SESSION_new();
+ if (sess == NULL
+ || !SSL_SESSION_set1_master_key(sess, pskdata,
+ pskdatalen)
+ || !SSL_SESSION_set_cipher(sess, cipher)
+ || !SSL_SESSION_set_protocol_version(sess,
+ TLS1_3_VERSION)) {
+ OPENSSL_cleanse(pskdata, pskdatalen);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ OPENSSL_cleanse(pskdata, pskdatalen);
+ }
+ }
+#endif /* OPENSSL_NO_PSK */
+
+ if (sess != NULL) {
+ /* We found a PSK */
+ SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
+
+ if (sesstmp == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
goto err;
- }
- SSL_SESSION_free(sess);
- sess = sesstmp;
-
- /*
- * We've just been told to use this session for this context so
- * make sure the sid_ctx matches up.
- */
- memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
- sess->sid_ctx_length = s->sid_ctx_length;
- ext = 1;
- if (id == 0)
- s->ext.early_data_ok = 1;
- s->ext.ticket_expected = 1;
- } else {
- uint32_t ticket_age = 0, now, agesec, agems;
- int ret;
-
- /*
- * If we are using anti-replay protection then we behave as if
- * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
- * is no point in using full stateless tickets.
- */
- if ((s->options & SSL_OP_NO_TICKET) != 0
- || (s->max_early_data > 0
- && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))
- ret = tls_get_stateful_ticket(s, &identity, &sess);
- else
- ret = tls_decrypt_ticket(s, PACKET_data(&identity),
- PACKET_remaining(&identity), NULL, 0,
- &sess);
-
- if (ret == SSL_TICKET_EMPTY) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
- return 0;
- }
-
- if (ret == SSL_TICKET_FATAL_ERR_MALLOC
- || ret == SSL_TICKET_FATAL_ERR_OTHER) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT)
- continue;
-
- /* Check for replay */
- if (s->max_early_data > 0
- && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0
- && !SSL_CTX_remove_session(s->session_ctx, sess)) {
- SSL_SESSION_free(sess);
- sess = NULL;
- continue;
- }
-
- ticket_age = (uint32_t)ticket_agel;
- now = (uint32_t)time(NULL);
- agesec = now - (uint32_t)sess->time;
- agems = agesec * (uint32_t)1000;
- ticket_age -= sess->ext.tick_age_add;
-
- /*
- * For simplicity we do our age calculations in seconds. If the
- * client does it in ms then it could appear that their ticket age
- * is longer than ours (our ticket age calculation should always be
- * slightly longer than the client's due to the network latency).
- * Therefore we add 1000ms to our age calculation to adjust for
- * rounding errors.
- */
- if (id == 0
- && sess->timeout >= (long)agesec
- && agems / (uint32_t)1000 == agesec
- && ticket_age <= agems + 1000
- && ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
- /*
- * Ticket age is within tolerance and not expired. We allow it
- * for early data
- */
- s->ext.early_data_ok = 1;
- }
- }
-
- md = ssl_md(sess->cipher->algorithm2);
- if (md != ssl_md(s->s3->tmp.new_cipher->algorithm2)) {
- /* The ciphersuite is not compatible with this session. */
- SSL_SESSION_free(sess);
- sess = NULL;
- s->ext.early_data_ok = 0;
- s->ext.ticket_expected = 0;
- continue;
- }
- break;
- }
-
- if (sess == NULL)
- return 1;
-
- binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
- hashsize = EVP_MD_size(md);
-
- if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
- goto err;
- }
-
- for (i = 0; i <= id; i++) {
- if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
- goto err;
- }
- }
-
- if (PACKET_remaining(&binder) != hashsize) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
- SSL_R_BAD_EXTENSION);
- goto err;
- }
- if (tls_psk_do_binder(s, md, (const unsigned char *)s->init_buf->data,
- binderoffset, PACKET_data(&binder), NULL, sess, 0,
- ext) != 1) {
- /* SSLfatal() already called */
- goto err;
- }
-
+ }
+ SSL_SESSION_free(sess);
+ sess = sesstmp;
+
+ /*
+ * We've just been told to use this session for this context so
+ * make sure the sid_ctx matches up.
+ */
+ memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
+ sess->sid_ctx_length = s->sid_ctx_length;
+ ext = 1;
+ if (id == 0)
+ s->ext.early_data_ok = 1;
+ s->ext.ticket_expected = 1;
+ } else {
+ uint32_t ticket_age = 0, now, agesec, agems;
+ int ret;
+
+ /*
+ * If we are using anti-replay protection then we behave as if
+ * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
+ * is no point in using full stateless tickets.
+ */
+ if ((s->options & SSL_OP_NO_TICKET) != 0
+ || (s->max_early_data > 0
+ && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))
+ ret = tls_get_stateful_ticket(s, &identity, &sess);
+ else
+ ret = tls_decrypt_ticket(s, PACKET_data(&identity),
+ PACKET_remaining(&identity), NULL, 0,
+ &sess);
+
+ if (ret == SSL_TICKET_EMPTY) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ SSL_R_BAD_EXTENSION);
+ return 0;
+ }
+
+ if (ret == SSL_TICKET_FATAL_ERR_MALLOC
+ || ret == SSL_TICKET_FATAL_ERR_OTHER) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT)
+ continue;
+
+ /* Check for replay */
+ if (s->max_early_data > 0
+ && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0
+ && !SSL_CTX_remove_session(s->session_ctx, sess)) {
+ SSL_SESSION_free(sess);
+ sess = NULL;
+ continue;
+ }
+
+ ticket_age = (uint32_t)ticket_agel;
+ now = (uint32_t)time(NULL);
+ agesec = now - (uint32_t)sess->time;
+ agems = agesec * (uint32_t)1000;
+ ticket_age -= sess->ext.tick_age_add;
+
+ /*
+ * For simplicity we do our age calculations in seconds. If the
+ * client does it in ms then it could appear that their ticket age
+ * is longer than ours (our ticket age calculation should always be
+ * slightly longer than the client's due to the network latency).
+ * Therefore we add 1000ms to our age calculation to adjust for
+ * rounding errors.
+ */
+ if (id == 0
+ && sess->timeout >= (long)agesec
+ && agems / (uint32_t)1000 == agesec
+ && ticket_age <= agems + 1000
+ && ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
+ /*
+ * Ticket age is within tolerance and not expired. We allow it
+ * for early data
+ */
+ s->ext.early_data_ok = 1;
+ }
+ }
+
+ md = ssl_md(sess->cipher->algorithm2);
+ if (md != ssl_md(s->s3->tmp.new_cipher->algorithm2)) {
+ /* The ciphersuite is not compatible with this session. */
+ SSL_SESSION_free(sess);
+ sess = NULL;
+ s->ext.early_data_ok = 0;
+ s->ext.ticket_expected = 0;
+ continue;
+ }
+ break;
+ }
+
+ if (sess == NULL)
+ return 1;
+
+ binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
+ hashsize = EVP_MD_size(md);
+
+ if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ SSL_R_BAD_EXTENSION);
+ goto err;
+ }
+
+ for (i = 0; i <= id; i++) {
+ if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ SSL_R_BAD_EXTENSION);
+ goto err;
+ }
+ }
+
+ if (PACKET_remaining(&binder) != hashsize) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+ SSL_R_BAD_EXTENSION);
+ goto err;
+ }
+ if (tls_psk_do_binder(s, md, (const unsigned char *)s->init_buf->data,
+ binderoffset, PACKET_data(&binder), NULL, sess, 0,
+ ext) != 1) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
s->ext.tick_identity = id;
-
- SSL_SESSION_free(s->session);
- s->session = sess;
- return 1;
-err:
- SSL_SESSION_free(sess);
- return 0;
-}
-
-int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH,
- SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR);
- return 0;
- }
-
- s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
-
- return 1;
-}
-
-/*
- * Add the server's renegotiation binding
- */
-EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (!s->s3->send_connection_binding)
- return EXT_RETURN_NOT_SENT;
-
- /* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)
- || !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
- s->s3->previous_client_finished_len)
- || !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
- s->s3->previous_server_finished_len)
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
+
+ SSL_SESSION_free(s->session);
+ s->session = sess;
+ return 1;
+err:
+ SSL_SESSION_free(sess);
+ return 0;
+}
+
+int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH,
+ SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR);
+ return 0;
+ }
+
+ s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
+
+ return 1;
+}
+
+/*
+ * Add the server's renegotiation binding
+ */
+EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (!s->s3->send_connection_binding)
+ return EXT_RETURN_NOT_SENT;
+
+ /* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u8(pkt)
+ || !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
+ s->s3->previous_client_finished_len)
+ || !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
+ s->s3->previous_server_finished_len)
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
if (s->servername_done != 1)
- return EXT_RETURN_NOT_SENT;
-
+ return EXT_RETURN_NOT_SENT;
+
/*
* Prior to TLSv1.3 we ignore any SNI in the current handshake if resuming.
* We just use the servername from the initial handshake.
@@ -1345,375 +1345,375 @@ EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
if (s->hit && !SSL_IS_TLS13(s))
return EXT_RETURN_NOT_SENT;
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-/* Add/include the server's max fragment len extension into ServerHello */
-EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
- return EXT_RETURN_NOT_SENT;
-
- /*-
- * 4 bytes for this extension type and extension length
- * 1 byte for the Max Fragment Length code value.
- */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-#ifndef OPENSSL_NO_EC
-EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
- int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+/* Add/include the server's max fragment len extension into ServerHello */
+EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
+ return EXT_RETURN_NOT_SENT;
+
+ /*-
+ * 4 bytes for this extension type and extension length
+ * 1 byte for the Max Fragment Length code value.
+ */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+#ifndef OPENSSL_NO_EC
+EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))
&& (s->ext.peer_ecpointformats != NULL);
- const unsigned char *plist;
- size_t plistlen;
-
- if (!using_ecc)
- return EXT_RETURN_NOT_SENT;
-
- tls1_get_formatlist(s, &plist, &plistlen);
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-#ifndef OPENSSL_NO_EC
-EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- const uint16_t *groups;
- size_t numgroups, i, first = 1;
-
- /* s->s3->group_id is non zero if we accepted a key_share */
- if (s->s3->group_id == 0)
- return EXT_RETURN_NOT_SENT;
-
- /* Get our list of supported groups */
- tls1_get_supported_groups(s, &groups, &numgroups);
- if (numgroups == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- /* Copy group ID if supported */
- for (i = 0; i < numgroups; i++) {
- uint16_t group = groups[i];
-
- if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
- if (first) {
- /*
- * Check if the client is already using our preferred group. If
- * so we don't need to add this extension
- */
- if (s->s3->group_id == group)
- return EXT_RETURN_NOT_SENT;
-
- /* Add extension header */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
- /* Sub-packet for supported_groups extension */
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- first = 0;
- }
- if (!WPACKET_put_bytes_u16(pkt, group)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- }
- }
-
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (!s->ext.ticket_expected || !tls_use_ticket(s)) {
- s->ext.ticket_expected = 0;
- return EXT_RETURN_NOT_SENT;
- }
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-#ifndef OPENSSL_NO_OCSP
-EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
+ const unsigned char *plist;
+ size_t plistlen;
+
+ if (!using_ecc)
+ return EXT_RETURN_NOT_SENT;
+
+ tls1_get_formatlist(s, &plist, &plistlen);
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ const uint16_t *groups;
+ size_t numgroups, i, first = 1;
+
+ /* s->s3->group_id is non zero if we accepted a key_share */
+ if (s->s3->group_id == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ /* Get our list of supported groups */
+ tls1_get_supported_groups(s, &groups, &numgroups);
+ if (numgroups == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ /* Copy group ID if supported */
+ for (i = 0; i < numgroups; i++) {
+ uint16_t group = groups[i];
+
+ if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
+ if (first) {
+ /*
+ * Check if the client is already using our preferred group. If
+ * so we don't need to add this extension
+ */
+ if (s->s3->group_id == group)
+ return EXT_RETURN_NOT_SENT;
+
+ /* Add extension header */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
+ /* Sub-packet for supported_groups extension */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ first = 0;
+ }
+ if (!WPACKET_put_bytes_u16(pkt, group)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ }
+ }
+
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (!s->ext.ticket_expected || !tls_use_ticket(s)) {
+ s->ext.ticket_expected = 0;
+ return EXT_RETURN_NOT_SENT;
+ }
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+#ifndef OPENSSL_NO_OCSP
+EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
/* We don't currently support this extension inside a CertificateRequest */
if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST)
return EXT_RETURN_NOT_SENT;
- if (!s->ext.status_expected)
- return EXT_RETURN_NOT_SENT;
-
- if (SSL_IS_TLS13(s) && chainidx != 0)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- /*
- * In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we
- * send back an empty extension, with the certificate status appearing as a
- * separate message
- */
- if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
- }
- if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
-EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- const unsigned char *npa;
- unsigned int npalen;
- int ret;
- int npn_seen = s->s3->npn_seen;
-
- s->s3->npn_seen = 0;
- if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL)
- return EXT_RETURN_NOT_SENT;
-
- ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen,
- s->ctx->ext.npn_advertised_cb_arg);
- if (ret == SSL_TLSEXT_ERR_OK) {
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
- || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- s->s3->npn_seen = 1;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (s->s3->alpn_selected == NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt,
- TLSEXT_TYPE_application_layer_protocol_negotiation)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
- s->s3->alpn_selected_len)
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-#ifndef OPENSSL_NO_SRTP
-EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (s->srtp_profile == NULL)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, 2)
- || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
- || !WPACKET_put_bytes_u8(pkt, 0)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-#endif
-
-EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (!s->ext.use_etm)
- return EXT_RETURN_NOT_SENT;
-
- /*
- * Don't use encrypt_then_mac if AEAD or RC4 might want to disable
- * for other cases too.
- */
- if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
- || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
- || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
- || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
- s->ext.use_etm = 0;
- return EXT_RETURN_NOT_SENT;
- }
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (!ossl_assert(SSL_IS_TLS13(s))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->version)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- unsigned char *encodedPoint;
- size_t encoded_pt_len = 0;
- EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
-
- if (s->hello_retry_request == SSL_HRR_PENDING) {
- if (ckey != NULL) {
- /* Original key_share was acceptable so don't ask for another one */
- return EXT_RETURN_NOT_SENT;
- }
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
- }
-
- if (ckey == NULL) {
- /* No key_share received from client - must be resuming */
- if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- return EXT_RETURN_NOT_SENT;
- }
+ if (!s->ext.status_expected)
+ return EXT_RETURN_NOT_SENT;
+
+ if (SSL_IS_TLS13(s) && chainidx != 0)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we
+ * send back an empty extension, with the certificate status appearing as a
+ * separate message
+ */
+ if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+ if (!WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ const unsigned char *npa;
+ unsigned int npalen;
+ int ret;
+ int npn_seen = s->s3->npn_seen;
+
+ s->s3->npn_seen = 0;
+ if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen,
+ s->ctx->ext.npn_advertised_cb_arg);
+ if (ret == SSL_TLSEXT_ERR_OK) {
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
+ || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ s->s3->npn_seen = 1;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (s->s3->alpn_selected == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt,
+ TLSEXT_TYPE_application_layer_protocol_negotiation)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
+ s->s3->alpn_selected_len)
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+#ifndef OPENSSL_NO_SRTP
+EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (s->srtp_profile == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u16(pkt, 2)
+ || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
+ || !WPACKET_put_bytes_u8(pkt, 0)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+#endif
+
+EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (!s->ext.use_etm)
+ return EXT_RETURN_NOT_SENT;
+
+ /*
+ * Don't use encrypt_then_mac if AEAD or RC4 might want to disable
+ * for other cases too.
+ */
+ if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
+ || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
+ || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
+ || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
+ s->ext.use_etm = 0;
+ return EXT_RETURN_NOT_SENT;
+ }
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (!ossl_assert(SSL_IS_TLS13(s))) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u16(pkt, s->version)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ unsigned char *encodedPoint;
+ size_t encoded_pt_len = 0;
+ EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
+
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
+ if (ckey != NULL) {
+ /* Original key_share was acceptable so don't ask for another one */
+ return EXT_RETURN_NOT_SENT;
+ }
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+ }
+
+ if (ckey == NULL) {
+ /* No key_share received from client - must be resuming */
+ if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ return EXT_RETURN_NOT_SENT;
+ }
if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) {
/*
* PSK ('hit') and explicitly not doing DHE (if the client sent the
@@ -1721,261 +1721,261 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
*/
return EXT_RETURN_NOT_SENT;
}
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- skey = ssl_generate_pkey(ckey);
- if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_MALLOC_FAILURE);
- return EXT_RETURN_FAIL;
- }
-
- /* Generate encoding of server key */
- encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
- if (encoded_pt_len == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_EC_LIB);
- EVP_PKEY_free(skey);
- return EXT_RETURN_FAIL;
- }
-
- if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
- ERR_R_INTERNAL_ERROR);
- EVP_PKEY_free(skey);
- OPENSSL_free(encodedPoint);
- return EXT_RETURN_FAIL;
- }
- OPENSSL_free(encodedPoint);
-
- /* This causes the crypto state to be updated based on the derived keys */
- s->s3->tmp.pkey = skey;
- if (ssl_derive(s, skey, ckey, 1) == 0) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
- }
- return EXT_RETURN_SENT;
-#else
- return EXT_RETURN_FAIL;
-#endif
-}
-
-EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
-#ifndef OPENSSL_NO_TLS1_3
- unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie;
- unsigned char *hmac, *hmac2;
- size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen;
- EVP_MD_CTX *hctx;
- EVP_PKEY *pkey;
- int ret = EXT_RETURN_FAIL;
-
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
- return EXT_RETURN_NOT_SENT;
-
- if (s->ctx->gen_stateless_cookie_cb == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- SSL_R_NO_COOKIE_CALLBACK_SET);
- return EXT_RETURN_FAIL;
- }
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_get_total_written(pkt, &startlen)
- || !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie)
- || !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION)
- || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION)
- || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
- || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt,
- &ciphlen)
- /* Is there a key_share extension present in this HRR? */
- || !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL)
- || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL))
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- /*
- * Get the hash of the initial ClientHello. ssl_handshake_hash() operates
- * on raw buffers, so we first reserve sufficient bytes (above) and then
- * subsequently allocate them (below)
- */
- if (!ssl3_digest_cached_records(s, 0)
- || !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) {
- /* SSLfatal() already called */
- return EXT_RETURN_FAIL;
- }
-
- if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2)
- || !ossl_assert(hashval1 == hashval2)
- || !WPACKET_close(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)
- || !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- /* Generate the application cookie */
- if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
- return EXT_RETURN_FAIL;
- }
-
- if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2)
- || !ossl_assert(appcookie1 == appcookie2)
- || !WPACKET_close(pkt)
- || !WPACKET_get_total_written(pkt, &totcookielen)
- || !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- hmaclen = SHA256_DIGEST_LENGTH;
-
- totcookielen -= startlen;
- if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- /* HMAC the cookie */
- hctx = EVP_MD_CTX_create();
- pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
- s->session_ctx->ext.cookie_hmac_key,
- sizeof(s->session_ctx->ext
- .cookie_hmac_key));
- if (hctx == NULL || pkey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
- || EVP_DigestSign(hctx, hmac, &hmaclen, cookie,
- totcookielen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2)
- || !ossl_assert(hmac == hmac2)
- || !ossl_assert(cookie == hmac - totcookielen)
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- ret = EXT_RETURN_SENT;
-
- err:
- EVP_MD_CTX_free(hctx);
- EVP_PKEY_free(pkey);
- return ret;
-#else
- return EXT_RETURN_FAIL;
-#endif
-}
-
-EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- const unsigned char cryptopro_ext[36] = {
- 0xfd, 0xe8, /* 65000 */
- 0x00, 0x20, /* 32 bytes length */
- 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
- 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
- 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
- 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
- };
-
- if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
- && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
- || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
- unsigned int context, X509 *x,
- size_t chainidx)
-{
- if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
- if (s->max_early_data == 0)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u32(pkt, s->max_early_data)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
- }
-
- if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
-
-EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
- X509 *x, size_t chainidx)
-{
- if (!s->hit)
- return EXT_RETURN_NOT_SENT;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
- || !WPACKET_start_sub_packet_u16(pkt)
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ skey = ssl_generate_pkey(ckey);
+ if (skey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+ ERR_R_MALLOC_FAILURE);
+ return EXT_RETURN_FAIL;
+ }
+
+ /* Generate encoding of server key */
+ encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
+ if (encoded_pt_len == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+ ERR_R_EC_LIB);
+ EVP_PKEY_free(skey);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+ ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(skey);
+ OPENSSL_free(encodedPoint);
+ return EXT_RETURN_FAIL;
+ }
+ OPENSSL_free(encodedPoint);
+
+ /* This causes the crypto state to be updated based on the derived keys */
+ s->s3->tmp.pkey = skey;
+ if (ssl_derive(s, skey, ckey, 1) == 0) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+ return EXT_RETURN_SENT;
+#else
+ return EXT_RETURN_FAIL;
+#endif
+}
+
+EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie;
+ unsigned char *hmac, *hmac2;
+ size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen;
+ EVP_MD_CTX *hctx;
+ EVP_PKEY *pkey;
+ int ret = EXT_RETURN_FAIL;
+
+ if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ if (s->ctx->gen_stateless_cookie_cb == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ SSL_R_NO_COOKIE_CALLBACK_SET);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_get_total_written(pkt, &startlen)
+ || !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie)
+ || !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION)
+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION)
+ || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
+ || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt,
+ &ciphlen)
+ /* Is there a key_share extension present in this HRR? */
+ || !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL)
+ || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL))
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * Get the hash of the initial ClientHello. ssl_handshake_hash() operates
+ * on raw buffers, so we first reserve sufficient bytes (above) and then
+ * subsequently allocate them (below)
+ */
+ if (!ssl3_digest_cached_records(s, 0)
+ || !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) {
+ /* SSLfatal() already called */
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2)
+ || !ossl_assert(hashval1 == hashval2)
+ || !WPACKET_close(pkt)
+ || !WPACKET_start_sub_packet_u8(pkt)
+ || !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ /* Generate the application cookie */
+ if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+ return EXT_RETURN_FAIL;
+ }
+
+ if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2)
+ || !ossl_assert(appcookie1 == appcookie2)
+ || !WPACKET_close(pkt)
+ || !WPACKET_get_total_written(pkt, &totcookielen)
+ || !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ hmaclen = SHA256_DIGEST_LENGTH;
+
+ totcookielen -= startlen;
+ if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ /* HMAC the cookie */
+ hctx = EVP_MD_CTX_create();
+ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
+ s->session_ctx->ext.cookie_hmac_key,
+ sizeof(s->session_ctx->ext
+ .cookie_hmac_key));
+ if (hctx == NULL || pkey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
+ || EVP_DigestSign(hctx, hmac, &hmaclen, cookie,
+ totcookielen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2)
+ || !ossl_assert(hmac == hmac2)
+ || !ossl_assert(cookie == hmac - totcookielen)
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = EXT_RETURN_SENT;
+
+ err:
+ EVP_MD_CTX_free(hctx);
+ EVP_PKEY_free(pkey);
+ return ret;
+#else
+ return EXT_RETURN_FAIL;
+#endif
+}
+
+EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ const unsigned char cryptopro_ext[36] = {
+ 0xfd, 0xe8, /* 65000 */
+ 0x00, 0x20, /* 32 bytes length */
+ 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
+ 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
+ 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
+ 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
+ };
+
+ if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
+ && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
+ || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx)
+{
+ if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
+ if (s->max_early_data == 0)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u32(pkt, s->max_early_data)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+ }
+
+ if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
+EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ if (!s->hit)
+ return EXT_RETURN_NOT_SENT;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
+ || !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
-
- return EXT_RETURN_SENT;
-}
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
diff --git a/contrib/libs/openssl/ssl/statem/statem.c b/contrib/libs/openssl/ssl/statem/statem.c
index 20f5bd584e..a9ee7d4502 100644
--- a/contrib/libs/openssl/ssl/statem/statem.c
+++ b/contrib/libs/openssl/ssl/statem/statem.c
@@ -1,972 +1,972 @@
-/*
- * Copyright 2015-2019 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 "internal/cryptlib.h"
-#include <openssl/rand.h>
+/*
+ * Copyright 2015-2019 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 "internal/cryptlib.h"
+#include <openssl/rand.h>
#include "../ssl_local.h"
#include "statem_local.h"
-#include <assert.h>
-
-/*
- * This file implements the SSL/TLS/DTLS state machines.
- *
- * There are two primary state machines:
- *
- * 1) Message flow state machine
- * 2) Handshake state machine
- *
- * The Message flow state machine controls the reading and sending of messages
- * including handling of non-blocking IO events, flushing of the underlying
- * write BIO, handling unexpected messages, etc. It is itself broken into two
- * separate sub-state machines which control reading and writing respectively.
- *
- * The Handshake state machine keeps track of the current SSL/TLS handshake
- * state. Transitions of the handshake state are the result of events that
- * occur within the Message flow state machine.
- *
- * Overall it looks like this:
- *
- * --------------------------------------------- -------------------
- * | | | |
- * | Message flow state machine | | |
- * | | | |
- * | -------------------- -------------------- | Transition | Handshake state |
- * | | MSG_FLOW_READING | | MSG_FLOW_WRITING | | Event | machine |
- * | | sub-state | | sub-state | |----------->| |
- * | | machine for | | machine for | | | |
- * | | reading messages | | writing messages | | | |
- * | -------------------- -------------------- | | |
- * | | | |
- * --------------------------------------------- -------------------
- *
- */
-
-/* Sub state machine return values */
-typedef enum {
- /* Something bad happened or NBIO */
- SUB_STATE_ERROR,
- /* Sub state finished go to the next sub state */
- SUB_STATE_FINISHED,
- /* Sub state finished and handshake was completed */
- SUB_STATE_END_HANDSHAKE
-} SUB_STATE_RETURN;
-
-static int state_machine(SSL *s, int server);
-static void init_read_state_machine(SSL *s);
-static SUB_STATE_RETURN read_state_machine(SSL *s);
-static void init_write_state_machine(SSL *s);
-static SUB_STATE_RETURN write_state_machine(SSL *s);
-
-OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
-{
- return ssl->statem.hand_state;
-}
-
-int SSL_in_init(const SSL *s)
-{
- return s->statem.in_init;
-}
-
-int SSL_is_init_finished(const SSL *s)
-{
- return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK);
-}
-
-int SSL_in_before(const SSL *s)
-{
- /*
- * Historically being "in before" meant before anything had happened. In the
- * current code though we remain in the "before" state for a while after we
- * have started the handshake process (e.g. as a server waiting for the
- * first message to arrive). There "in before" is taken to mean "in before"
- * and not started any handshake process yet.
- */
- return (s->statem.hand_state == TLS_ST_BEFORE)
- && (s->statem.state == MSG_FLOW_UNINITED);
-}
-
-/*
- * Clear the state machine state and reset back to MSG_FLOW_UNINITED
- */
-void ossl_statem_clear(SSL *s)
-{
- s->statem.state = MSG_FLOW_UNINITED;
- s->statem.hand_state = TLS_ST_BEFORE;
- s->statem.in_init = 1;
- s->statem.no_cert_verify = 0;
-}
-
-/*
- * Set the state machine up ready for a renegotiation handshake
- */
-void ossl_statem_set_renegotiate(SSL *s)
-{
- s->statem.in_init = 1;
- s->statem.request_state = TLS_ST_SW_HELLO_REQ;
-}
-
-/*
- * Put the state machine into an error state and send an alert if appropriate.
- * This is a permanent error for the current connection.
- */
-void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
- int line)
-{
- ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
- /* We shouldn't call SSLfatal() twice. Once is enough */
- if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR)
- return;
- s->statem.in_init = 1;
- s->statem.state = MSG_FLOW_ERROR;
- if (al != SSL_AD_NO_ALERT
- && s->statem.enc_write_state != ENC_WRITE_STATE_INVALID)
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
-}
-
-/*
- * This macro should only be called if we are already expecting to be in
- * a fatal error state. We verify that we are, and set it if not (this would
- * indicate a bug).
- */
-#define check_fatal(s, f) \
- do { \
- if (!ossl_assert((s)->statem.in_init \
- && (s)->statem.state == MSG_FLOW_ERROR)) \
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
- SSL_R_MISSING_FATAL); \
- } while (0)
-
-/*
- * Discover whether the current connection is in the error state.
- *
- * Valid return values are:
- * 1: Yes
- * 0: No
- */
-int ossl_statem_in_error(const SSL *s)
-{
- if (s->statem.state == MSG_FLOW_ERROR)
- return 1;
-
- return 0;
-}
-
-void ossl_statem_set_in_init(SSL *s, int init)
-{
- s->statem.in_init = init;
-}
-
-int ossl_statem_get_in_handshake(SSL *s)
-{
- return s->statem.in_handshake;
-}
-
-void ossl_statem_set_in_handshake(SSL *s, int inhand)
-{
- if (inhand)
- s->statem.in_handshake++;
- else
- s->statem.in_handshake--;
-}
-
-/* Are we in a sensible state to skip over unreadable early data? */
-int ossl_statem_skip_early_data(SSL *s)
-{
- if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
- return 0;
-
- if (!s->server
- || s->statem.hand_state != TLS_ST_EARLY_DATA
- || s->hello_retry_request == SSL_HRR_COMPLETE)
- return 0;
-
- return 1;
-}
-
-/*
- * Called when we are in SSL_read*(), SSL_write*(), or SSL_accept()
- * /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early
- * data state and whether we should attempt to move the handshake on if so.
- * |sending| is 1 if we are attempting to send data (SSL_write*()), 0 if we are
- * attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake()
- * or similar.
- */
-void ossl_statem_check_finish_init(SSL *s, int sending)
-{
- if (sending == -1) {
- if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
- || s->statem.hand_state == TLS_ST_EARLY_DATA) {
- ossl_statem_set_in_init(s, 1);
- if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
- /*
- * SSL_connect() or SSL_do_handshake() has been called directly.
- * We don't allow any more writing of early data.
- */
- s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
- }
- }
- } else if (!s->server) {
- if ((sending && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
- || s->statem.hand_state == TLS_ST_EARLY_DATA)
- && s->early_data_state != SSL_EARLY_DATA_WRITING)
- || (!sending && s->statem.hand_state == TLS_ST_EARLY_DATA)) {
- ossl_statem_set_in_init(s, 1);
- /*
- * SSL_write() has been called directly. We don't allow any more
- * writing of early data.
- */
- if (sending && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
- s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
- }
- } else {
- if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
- && s->statem.hand_state == TLS_ST_EARLY_DATA)
- ossl_statem_set_in_init(s, 1);
- }
-}
-
-void ossl_statem_set_hello_verify_done(SSL *s)
-{
- s->statem.state = MSG_FLOW_UNINITED;
- s->statem.in_init = 1;
- /*
- * This will get reset (briefly) back to TLS_ST_BEFORE when we enter
- * state_machine() because |state| is MSG_FLOW_UNINITED, but until then any
- * calls to SSL_in_before() will return false. Also calls to
- * SSL_state_string() and SSL_state_string_long() will return something
- * sensible.
- */
- s->statem.hand_state = TLS_ST_SR_CLNT_HELLO;
-}
-
-int ossl_statem_connect(SSL *s)
-{
- return state_machine(s, 0);
-}
-
-int ossl_statem_accept(SSL *s)
-{
- return state_machine(s, 1);
-}
-
-typedef void (*info_cb) (const SSL *, int, int);
-
-static info_cb get_callback(SSL *s)
-{
- if (s->info_callback != NULL)
- return s->info_callback;
- else if (s->ctx->info_callback != NULL)
- return s->ctx->info_callback;
-
- return NULL;
-}
-
-/*
- * The main message flow state machine. We start in the MSG_FLOW_UNINITED or
- * MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and
- * transitions are as follows:
- *
- * MSG_FLOW_UNINITED MSG_FLOW_FINISHED
- * | |
- * +-----------------------+
- * v
- * MSG_FLOW_WRITING <---> MSG_FLOW_READING
- * |
- * V
- * MSG_FLOW_FINISHED
- * |
- * V
- * [SUCCESS]
- *
- * We may exit at any point due to an error or NBIO event. If an NBIO event
- * occurs then we restart at the point we left off when we are recalled.
- * MSG_FLOW_WRITING and MSG_FLOW_READING have sub-state machines associated with them.
- *
- * In addition to the above there is also the MSG_FLOW_ERROR state. We can move
- * into that state at any point in the event that an irrecoverable error occurs.
- *
- * Valid return values are:
- * 1: Success
- * <=0: NBIO or error
- */
-static int state_machine(SSL *s, int server)
-{
- BUF_MEM *buf = NULL;
- void (*cb) (const SSL *ssl, int type, int val) = NULL;
- OSSL_STATEM *st = &s->statem;
- int ret = -1;
- int ssret;
-
- if (st->state == MSG_FLOW_ERROR) {
- /* Shouldn't have been called if we're already in the error state */
- return -1;
- }
-
- ERR_clear_error();
- clear_sys_error();
-
- cb = get_callback(s);
-
- st->in_handshake++;
- if (!SSL_in_init(s) || SSL_in_before(s)) {
- /*
- * If we are stateless then we already called SSL_clear() - don't do
- * it again and clear the STATELESS flag itself.
- */
- if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s))
- return -1;
- }
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
- /*
- * Notify SCTP BIO socket to enter handshake mode and prevent stream
- * identifier other than 0.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
- st->in_handshake, NULL);
- }
-#endif
-
- /* Initialise state machine */
- if (st->state == MSG_FLOW_UNINITED
- || st->state == MSG_FLOW_FINISHED) {
- if (st->state == MSG_FLOW_UNINITED) {
- st->hand_state = TLS_ST_BEFORE;
- st->request_state = TLS_ST_BEFORE;
- }
-
- s->server = server;
- if (cb != NULL) {
- if (SSL_IS_FIRST_HANDSHAKE(s) || !SSL_IS_TLS13(s))
- cb(s, SSL_CB_HANDSHAKE_START, 1);
- }
-
- /*
- * Fatal errors in this block don't send an alert because we have
- * failed to even initialise properly. Sending an alert is probably
- * doomed to failure.
- */
-
- if (SSL_IS_DTLS(s)) {
- if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
- (server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
- } else {
- if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
- }
-
- if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
-
- if (s->init_buf == NULL) {
- if ((buf = BUF_MEM_new()) == NULL) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
- if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
- s->init_buf = buf;
- buf = NULL;
- }
-
- if (!ssl3_setup_buffers(s)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
- s->init_num = 0;
-
- /*
- * Should have been reset by tls_process_finished, too.
- */
- s->s3->change_cipher_spec = 0;
-
- /*
- * Ok, we now need to push on a buffering BIO ...but not with
- * SCTP
- */
-#ifndef OPENSSL_NO_SCTP
- if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
-#endif
- if (!ssl_init_wbio_buffer(s)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- goto end;
- }
-
- if ((SSL_in_before(s))
- || s->renegotiate) {
- if (!tls_setup_handshake(s)) {
- /* SSLfatal() already called */
- goto end;
- }
-
- if (SSL_IS_FIRST_HANDSHAKE(s))
- st->read_state_first_init = 1;
- }
-
- st->state = MSG_FLOW_WRITING;
- init_write_state_machine(s);
- }
-
- while (st->state != MSG_FLOW_FINISHED) {
- if (st->state == MSG_FLOW_READING) {
- ssret = read_state_machine(s);
- if (ssret == SUB_STATE_FINISHED) {
- st->state = MSG_FLOW_WRITING;
- init_write_state_machine(s);
- } else {
- /* NBIO or error */
- goto end;
- }
- } else if (st->state == MSG_FLOW_WRITING) {
- ssret = write_state_machine(s);
- if (ssret == SUB_STATE_FINISHED) {
- st->state = MSG_FLOW_READING;
- init_read_state_machine(s);
- } else if (ssret == SUB_STATE_END_HANDSHAKE) {
- st->state = MSG_FLOW_FINISHED;
- } else {
- /* NBIO or error */
- goto end;
- }
- } else {
- /* Error */
- check_fatal(s, SSL_F_STATE_MACHINE);
- SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- goto end;
- }
- }
-
- ret = 1;
-
- end:
- st->in_handshake--;
-
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
- /*
- * Notify SCTP BIO socket to leave handshake mode and allow stream
- * identifier other than 0.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
- st->in_handshake, NULL);
- }
-#endif
-
- BUF_MEM_free(buf);
- if (cb != NULL) {
- if (server)
- cb(s, SSL_CB_ACCEPT_EXIT, ret);
- else
- cb(s, SSL_CB_CONNECT_EXIT, ret);
- }
- return ret;
-}
-
-/*
- * Initialise the MSG_FLOW_READING sub-state machine
- */
-static void init_read_state_machine(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- st->read_state = READ_STATE_HEADER;
-}
-
-static int grow_init_buf(SSL *s, size_t size) {
-
- size_t msg_offset = (char *)s->init_msg - s->init_buf->data;
-
- if (!BUF_MEM_grow_clean(s->init_buf, (int)size))
- return 0;
-
- if (size < msg_offset)
- return 0;
-
- s->init_msg = s->init_buf->data + msg_offset;
-
- return 1;
-}
-
-/*
- * This function implements the sub-state machine when the message flow is in
- * MSG_FLOW_READING. The valid sub-states and transitions are:
- *
- * READ_STATE_HEADER <--+<-------------+
- * | | |
- * v | |
- * READ_STATE_BODY -----+-->READ_STATE_POST_PROCESS
- * | |
- * +----------------------------+
- * v
- * [SUB_STATE_FINISHED]
- *
- * READ_STATE_HEADER has the responsibility for reading in the message header
- * and transitioning the state of the handshake state machine.
- *
- * READ_STATE_BODY reads in the rest of the message and then subsequently
- * processes it.
- *
- * READ_STATE_POST_PROCESS is an optional step that may occur if some post
- * processing activity performed on the message may block.
- *
- * Any of the above states could result in an NBIO event occurring in which case
- * control returns to the calling application. When this function is recalled we
- * will resume in the same state where we left off.
- */
-static SUB_STATE_RETURN read_state_machine(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
- int ret, mt;
- size_t len = 0;
- int (*transition) (SSL *s, int mt);
- PACKET pkt;
- MSG_PROCESS_RETURN(*process_message) (SSL *s, PACKET *pkt);
- WORK_STATE(*post_process_message) (SSL *s, WORK_STATE wst);
- size_t (*max_message_size) (SSL *s);
- void (*cb) (const SSL *ssl, int type, int val) = NULL;
-
- cb = get_callback(s);
-
- if (s->server) {
- transition = ossl_statem_server_read_transition;
- process_message = ossl_statem_server_process_message;
- max_message_size = ossl_statem_server_max_message_size;
- post_process_message = ossl_statem_server_post_process_message;
- } else {
- transition = ossl_statem_client_read_transition;
- process_message = ossl_statem_client_process_message;
- max_message_size = ossl_statem_client_max_message_size;
- post_process_message = ossl_statem_client_post_process_message;
- }
-
- if (st->read_state_first_init) {
- s->first_packet = 1;
- st->read_state_first_init = 0;
- }
-
- while (1) {
- switch (st->read_state) {
- case READ_STATE_HEADER:
- /* Get the state the peer wants to move to */
- if (SSL_IS_DTLS(s)) {
- /*
- * In DTLS we get the whole message in one go - header and body
- */
- ret = dtls_get_message(s, &mt, &len);
- } else {
- ret = tls_get_message_header(s, &mt);
- }
-
- if (ret == 0) {
- /* Could be non-blocking IO */
- return SUB_STATE_ERROR;
- }
-
- if (cb != NULL) {
- /* Notify callback of an impending state change */
- if (s->server)
- cb(s, SSL_CB_ACCEPT_LOOP, 1);
- else
- cb(s, SSL_CB_CONNECT_LOOP, 1);
- }
- /*
- * Validate that we are allowed to move to the new state and move
- * to that state if so
- */
- if (!transition(s, mt))
- return SUB_STATE_ERROR;
-
- if (s->s3->tmp.message_size > max_message_size(s)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
- SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return SUB_STATE_ERROR;
- }
-
- /* dtls_get_message already did this */
- if (!SSL_IS_DTLS(s)
- && s->s3->tmp.message_size > 0
- && !grow_init_buf(s, s->s3->tmp.message_size
- + SSL3_HM_HEADER_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
- ERR_R_BUF_LIB);
- return SUB_STATE_ERROR;
- }
-
- st->read_state = READ_STATE_BODY;
- /* Fall through */
-
- case READ_STATE_BODY:
- if (!SSL_IS_DTLS(s)) {
- /* We already got this above for DTLS */
- ret = tls_get_message_body(s, &len);
- if (ret == 0) {
- /* Could be non-blocking IO */
- return SUB_STATE_ERROR;
- }
- }
-
- s->first_packet = 0;
- if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- return SUB_STATE_ERROR;
- }
- ret = process_message(s, &pkt);
-
- /* Discard the packet data */
- s->init_num = 0;
-
- switch (ret) {
- case MSG_PROCESS_ERROR:
- check_fatal(s, SSL_F_READ_STATE_MACHINE);
- return SUB_STATE_ERROR;
-
- case MSG_PROCESS_FINISHED_READING:
- if (SSL_IS_DTLS(s)) {
- dtls1_stop_timer(s);
- }
- return SUB_STATE_FINISHED;
-
- case MSG_PROCESS_CONTINUE_PROCESSING:
- st->read_state = READ_STATE_POST_PROCESS;
- st->read_state_work = WORK_MORE_A;
- break;
-
- default:
- st->read_state = READ_STATE_HEADER;
- break;
- }
- break;
-
- case READ_STATE_POST_PROCESS:
- st->read_state_work = post_process_message(s, st->read_state_work);
- switch (st->read_state_work) {
- case WORK_ERROR:
- check_fatal(s, SSL_F_READ_STATE_MACHINE);
- /* Fall through */
- case WORK_MORE_A:
- case WORK_MORE_B:
- case WORK_MORE_C:
- return SUB_STATE_ERROR;
-
- case WORK_FINISHED_CONTINUE:
- st->read_state = READ_STATE_HEADER;
- break;
-
- case WORK_FINISHED_STOP:
- if (SSL_IS_DTLS(s)) {
- dtls1_stop_timer(s);
- }
- return SUB_STATE_FINISHED;
- }
- break;
-
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- return SUB_STATE_ERROR;
- }
- }
-}
-
-/*
- * Send a previously constructed message to the peer.
- */
-static int statem_do_write(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- if (st->hand_state == TLS_ST_CW_CHANGE
- || st->hand_state == TLS_ST_SW_CHANGE) {
- if (SSL_IS_DTLS(s))
- return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
- else
- return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
- } else {
- return ssl_do_write(s);
- }
-}
-
-/*
- * Initialise the MSG_FLOW_WRITING sub-state machine
- */
-static void init_write_state_machine(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- st->write_state = WRITE_STATE_TRANSITION;
-}
-
-/*
- * This function implements the sub-state machine when the message flow is in
- * MSG_FLOW_WRITING. The valid sub-states and transitions are:
- *
- * +-> WRITE_STATE_TRANSITION ------> [SUB_STATE_FINISHED]
- * | |
- * | v
- * | WRITE_STATE_PRE_WORK -----> [SUB_STATE_END_HANDSHAKE]
- * | |
- * | v
- * | WRITE_STATE_SEND
- * | |
- * | v
- * | WRITE_STATE_POST_WORK
- * | |
- * +-------------+
- *
- * WRITE_STATE_TRANSITION transitions the state of the handshake state machine
-
- * WRITE_STATE_PRE_WORK performs any work necessary to prepare the later
- * sending of the message. This could result in an NBIO event occurring in
- * which case control returns to the calling application. When this function
- * is recalled we will resume in the same state where we left off.
- *
- * WRITE_STATE_SEND sends the message and performs any work to be done after
- * sending.
- *
- * WRITE_STATE_POST_WORK performs any work necessary after the sending of the
- * message has been completed. As for WRITE_STATE_PRE_WORK this could also
- * result in an NBIO event.
- */
-static SUB_STATE_RETURN write_state_machine(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
- int ret;
- WRITE_TRAN(*transition) (SSL *s);
- WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst);
- WORK_STATE(*post_work) (SSL *s, WORK_STATE wst);
- int (*get_construct_message_f) (SSL *s, WPACKET *pkt,
- int (**confunc) (SSL *s, WPACKET *pkt),
- int *mt);
- void (*cb) (const SSL *ssl, int type, int val) = NULL;
- int (*confunc) (SSL *s, WPACKET *pkt);
- int mt;
- WPACKET pkt;
-
- cb = get_callback(s);
-
- if (s->server) {
- transition = ossl_statem_server_write_transition;
- pre_work = ossl_statem_server_pre_work;
- post_work = ossl_statem_server_post_work;
- get_construct_message_f = ossl_statem_server_construct_message;
- } else {
- transition = ossl_statem_client_write_transition;
- pre_work = ossl_statem_client_pre_work;
- post_work = ossl_statem_client_post_work;
- get_construct_message_f = ossl_statem_client_construct_message;
- }
-
- while (1) {
- switch (st->write_state) {
- case WRITE_STATE_TRANSITION:
- if (cb != NULL) {
- /* Notify callback of an impending state change */
- if (s->server)
- cb(s, SSL_CB_ACCEPT_LOOP, 1);
- else
- cb(s, SSL_CB_CONNECT_LOOP, 1);
- }
- switch (transition(s)) {
- case WRITE_TRAN_CONTINUE:
- st->write_state = WRITE_STATE_PRE_WORK;
- st->write_state_work = WORK_MORE_A;
- break;
-
- case WRITE_TRAN_FINISHED:
- return SUB_STATE_FINISHED;
- break;
-
- case WRITE_TRAN_ERROR:
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
- return SUB_STATE_ERROR;
- }
- break;
-
- case WRITE_STATE_PRE_WORK:
- switch (st->write_state_work = pre_work(s, st->write_state_work)) {
- case WORK_ERROR:
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
- /* Fall through */
- case WORK_MORE_A:
- case WORK_MORE_B:
- case WORK_MORE_C:
- return SUB_STATE_ERROR;
-
- case WORK_FINISHED_CONTINUE:
- st->write_state = WRITE_STATE_SEND;
- break;
-
- case WORK_FINISHED_STOP:
- return SUB_STATE_END_HANDSHAKE;
- }
- if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
- /* SSLfatal() already called */
- return SUB_STATE_ERROR;
- }
- if (mt == SSL3_MT_DUMMY) {
- /* Skip construction and sending. This isn't a "real" state */
- st->write_state = WRITE_STATE_POST_WORK;
- st->write_state_work = WORK_MORE_A;
- break;
- }
- if (!WPACKET_init(&pkt, s->init_buf)
- || !ssl_set_handshake_header(s, &pkt, mt)) {
- WPACKET_cleanup(&pkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- return SUB_STATE_ERROR;
- }
- if (confunc != NULL && !confunc(s, &pkt)) {
- WPACKET_cleanup(&pkt);
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
- return SUB_STATE_ERROR;
- }
- if (!ssl_close_construct_packet(s, &pkt, mt)
- || !WPACKET_finish(&pkt)) {
- WPACKET_cleanup(&pkt);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- return SUB_STATE_ERROR;
- }
-
- /* Fall through */
-
- case WRITE_STATE_SEND:
- if (SSL_IS_DTLS(s) && st->use_timer) {
- dtls1_start_timer(s);
- }
- ret = statem_do_write(s);
- if (ret <= 0) {
- return SUB_STATE_ERROR;
- }
- st->write_state = WRITE_STATE_POST_WORK;
- st->write_state_work = WORK_MORE_A;
- /* Fall through */
-
- case WRITE_STATE_POST_WORK:
- switch (st->write_state_work = post_work(s, st->write_state_work)) {
- case WORK_ERROR:
- check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
- /* Fall through */
- case WORK_MORE_A:
- case WORK_MORE_B:
- case WORK_MORE_C:
- return SUB_STATE_ERROR;
-
- case WORK_FINISHED_CONTINUE:
- st->write_state = WRITE_STATE_TRANSITION;
- break;
-
- case WORK_FINISHED_STOP:
- return SUB_STATE_END_HANDSHAKE;
- }
- break;
-
- default:
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
- ERR_R_INTERNAL_ERROR);
- return SUB_STATE_ERROR;
- }
- }
-}
-
-/*
- * Flush the write BIO
- */
-int statem_flush(SSL *s)
-{
- s->rwstate = SSL_WRITING;
- if (BIO_flush(s->wbio) <= 0) {
- return 0;
- }
- s->rwstate = SSL_NOTHING;
-
- return 1;
-}
-
-/*
- * Called by the record layer to determine whether application data is
- * allowed to be received in the current handshake state or not.
- *
- * Return values are:
- * 1: Yes (application data allowed)
- * 0: No (application data not allowed)
- */
-int ossl_statem_app_data_allowed(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- if (st->state == MSG_FLOW_UNINITED)
- return 0;
-
- if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0))
- return 0;
-
- if (s->server) {
- /*
- * If we're a server and we haven't got as far as writing our
- * ServerHello yet then we allow app data
- */
- if (st->hand_state == TLS_ST_BEFORE
- || st->hand_state == TLS_ST_SR_CLNT_HELLO)
- return 1;
- } else {
- /*
- * If we're a client and we haven't read the ServerHello yet then we
- * allow app data
- */
- if (st->hand_state == TLS_ST_CW_CLNT_HELLO)
- return 1;
- }
-
- return 0;
-}
-
-/*
- * This function returns 1 if TLS exporter is ready to export keying
- * material, or 0 if otherwise.
- */
-int ossl_statem_export_allowed(SSL *s)
-{
- return s->s3->previous_server_finished_len != 0
- && s->statem.hand_state != TLS_ST_SW_FINISHED;
-}
-
-/*
- * Return 1 if early TLS exporter is ready to export keying material,
- * or 0 if otherwise.
- */
-int ossl_statem_export_early_allowed(SSL *s)
-{
- /*
- * The early exporter secret is only present on the server if we
- * have accepted early_data. It is present on the client as long
- * as we have sent early_data.
- */
- return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
- || (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT);
-}
+#include <assert.h>
+
+/*
+ * This file implements the SSL/TLS/DTLS state machines.
+ *
+ * There are two primary state machines:
+ *
+ * 1) Message flow state machine
+ * 2) Handshake state machine
+ *
+ * The Message flow state machine controls the reading and sending of messages
+ * including handling of non-blocking IO events, flushing of the underlying
+ * write BIO, handling unexpected messages, etc. It is itself broken into two
+ * separate sub-state machines which control reading and writing respectively.
+ *
+ * The Handshake state machine keeps track of the current SSL/TLS handshake
+ * state. Transitions of the handshake state are the result of events that
+ * occur within the Message flow state machine.
+ *
+ * Overall it looks like this:
+ *
+ * --------------------------------------------- -------------------
+ * | | | |
+ * | Message flow state machine | | |
+ * | | | |
+ * | -------------------- -------------------- | Transition | Handshake state |
+ * | | MSG_FLOW_READING | | MSG_FLOW_WRITING | | Event | machine |
+ * | | sub-state | | sub-state | |----------->| |
+ * | | machine for | | machine for | | | |
+ * | | reading messages | | writing messages | | | |
+ * | -------------------- -------------------- | | |
+ * | | | |
+ * --------------------------------------------- -------------------
+ *
+ */
+
+/* Sub state machine return values */
+typedef enum {
+ /* Something bad happened or NBIO */
+ SUB_STATE_ERROR,
+ /* Sub state finished go to the next sub state */
+ SUB_STATE_FINISHED,
+ /* Sub state finished and handshake was completed */
+ SUB_STATE_END_HANDSHAKE
+} SUB_STATE_RETURN;
+
+static int state_machine(SSL *s, int server);
+static void init_read_state_machine(SSL *s);
+static SUB_STATE_RETURN read_state_machine(SSL *s);
+static void init_write_state_machine(SSL *s);
+static SUB_STATE_RETURN write_state_machine(SSL *s);
+
+OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
+{
+ return ssl->statem.hand_state;
+}
+
+int SSL_in_init(const SSL *s)
+{
+ return s->statem.in_init;
+}
+
+int SSL_is_init_finished(const SSL *s)
+{
+ return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK);
+}
+
+int SSL_in_before(const SSL *s)
+{
+ /*
+ * Historically being "in before" meant before anything had happened. In the
+ * current code though we remain in the "before" state for a while after we
+ * have started the handshake process (e.g. as a server waiting for the
+ * first message to arrive). There "in before" is taken to mean "in before"
+ * and not started any handshake process yet.
+ */
+ return (s->statem.hand_state == TLS_ST_BEFORE)
+ && (s->statem.state == MSG_FLOW_UNINITED);
+}
+
+/*
+ * Clear the state machine state and reset back to MSG_FLOW_UNINITED
+ */
+void ossl_statem_clear(SSL *s)
+{
+ s->statem.state = MSG_FLOW_UNINITED;
+ s->statem.hand_state = TLS_ST_BEFORE;
+ s->statem.in_init = 1;
+ s->statem.no_cert_verify = 0;
+}
+
+/*
+ * Set the state machine up ready for a renegotiation handshake
+ */
+void ossl_statem_set_renegotiate(SSL *s)
+{
+ s->statem.in_init = 1;
+ s->statem.request_state = TLS_ST_SW_HELLO_REQ;
+}
+
+/*
+ * Put the state machine into an error state and send an alert if appropriate.
+ * This is a permanent error for the current connection.
+ */
+void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
+ int line)
+{
+ ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
+ /* We shouldn't call SSLfatal() twice. Once is enough */
+ if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR)
+ return;
+ s->statem.in_init = 1;
+ s->statem.state = MSG_FLOW_ERROR;
+ if (al != SSL_AD_NO_ALERT
+ && s->statem.enc_write_state != ENC_WRITE_STATE_INVALID)
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+}
+
+/*
+ * This macro should only be called if we are already expecting to be in
+ * a fatal error state. We verify that we are, and set it if not (this would
+ * indicate a bug).
+ */
+#define check_fatal(s, f) \
+ do { \
+ if (!ossl_assert((s)->statem.in_init \
+ && (s)->statem.state == MSG_FLOW_ERROR)) \
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
+ SSL_R_MISSING_FATAL); \
+ } while (0)
+
+/*
+ * Discover whether the current connection is in the error state.
+ *
+ * Valid return values are:
+ * 1: Yes
+ * 0: No
+ */
+int ossl_statem_in_error(const SSL *s)
+{
+ if (s->statem.state == MSG_FLOW_ERROR)
+ return 1;
+
+ return 0;
+}
+
+void ossl_statem_set_in_init(SSL *s, int init)
+{
+ s->statem.in_init = init;
+}
+
+int ossl_statem_get_in_handshake(SSL *s)
+{
+ return s->statem.in_handshake;
+}
+
+void ossl_statem_set_in_handshake(SSL *s, int inhand)
+{
+ if (inhand)
+ s->statem.in_handshake++;
+ else
+ s->statem.in_handshake--;
+}
+
+/* Are we in a sensible state to skip over unreadable early data? */
+int ossl_statem_skip_early_data(SSL *s)
+{
+ if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
+ return 0;
+
+ if (!s->server
+ || s->statem.hand_state != TLS_ST_EARLY_DATA
+ || s->hello_retry_request == SSL_HRR_COMPLETE)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Called when we are in SSL_read*(), SSL_write*(), or SSL_accept()
+ * /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early
+ * data state and whether we should attempt to move the handshake on if so.
+ * |sending| is 1 if we are attempting to send data (SSL_write*()), 0 if we are
+ * attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake()
+ * or similar.
+ */
+void ossl_statem_check_finish_init(SSL *s, int sending)
+{
+ if (sending == -1) {
+ if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
+ || s->statem.hand_state == TLS_ST_EARLY_DATA) {
+ ossl_statem_set_in_init(s, 1);
+ if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
+ /*
+ * SSL_connect() or SSL_do_handshake() has been called directly.
+ * We don't allow any more writing of early data.
+ */
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ }
+ }
+ } else if (!s->server) {
+ if ((sending && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
+ || s->statem.hand_state == TLS_ST_EARLY_DATA)
+ && s->early_data_state != SSL_EARLY_DATA_WRITING)
+ || (!sending && s->statem.hand_state == TLS_ST_EARLY_DATA)) {
+ ossl_statem_set_in_init(s, 1);
+ /*
+ * SSL_write() has been called directly. We don't allow any more
+ * writing of early data.
+ */
+ if (sending && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ }
+ } else {
+ if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
+ && s->statem.hand_state == TLS_ST_EARLY_DATA)
+ ossl_statem_set_in_init(s, 1);
+ }
+}
+
+void ossl_statem_set_hello_verify_done(SSL *s)
+{
+ s->statem.state = MSG_FLOW_UNINITED;
+ s->statem.in_init = 1;
+ /*
+ * This will get reset (briefly) back to TLS_ST_BEFORE when we enter
+ * state_machine() because |state| is MSG_FLOW_UNINITED, but until then any
+ * calls to SSL_in_before() will return false. Also calls to
+ * SSL_state_string() and SSL_state_string_long() will return something
+ * sensible.
+ */
+ s->statem.hand_state = TLS_ST_SR_CLNT_HELLO;
+}
+
+int ossl_statem_connect(SSL *s)
+{
+ return state_machine(s, 0);
+}
+
+int ossl_statem_accept(SSL *s)
+{
+ return state_machine(s, 1);
+}
+
+typedef void (*info_cb) (const SSL *, int, int);
+
+static info_cb get_callback(SSL *s)
+{
+ if (s->info_callback != NULL)
+ return s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ return s->ctx->info_callback;
+
+ return NULL;
+}
+
+/*
+ * The main message flow state machine. We start in the MSG_FLOW_UNINITED or
+ * MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and
+ * transitions are as follows:
+ *
+ * MSG_FLOW_UNINITED MSG_FLOW_FINISHED
+ * | |
+ * +-----------------------+
+ * v
+ * MSG_FLOW_WRITING <---> MSG_FLOW_READING
+ * |
+ * V
+ * MSG_FLOW_FINISHED
+ * |
+ * V
+ * [SUCCESS]
+ *
+ * We may exit at any point due to an error or NBIO event. If an NBIO event
+ * occurs then we restart at the point we left off when we are recalled.
+ * MSG_FLOW_WRITING and MSG_FLOW_READING have sub-state machines associated with them.
+ *
+ * In addition to the above there is also the MSG_FLOW_ERROR state. We can move
+ * into that state at any point in the event that an irrecoverable error occurs.
+ *
+ * Valid return values are:
+ * 1: Success
+ * <=0: NBIO or error
+ */
+static int state_machine(SSL *s, int server)
+{
+ BUF_MEM *buf = NULL;
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ OSSL_STATEM *st = &s->statem;
+ int ret = -1;
+ int ssret;
+
+ if (st->state == MSG_FLOW_ERROR) {
+ /* Shouldn't have been called if we're already in the error state */
+ return -1;
+ }
+
+ ERR_clear_error();
+ clear_sys_error();
+
+ cb = get_callback(s);
+
+ st->in_handshake++;
+ if (!SSL_in_init(s) || SSL_in_before(s)) {
+ /*
+ * If we are stateless then we already called SSL_clear() - don't do
+ * it again and clear the STATELESS flag itself.
+ */
+ if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s))
+ return -1;
+ }
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ /*
+ * Notify SCTP BIO socket to enter handshake mode and prevent stream
+ * identifier other than 0.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ st->in_handshake, NULL);
+ }
+#endif
+
+ /* Initialise state machine */
+ if (st->state == MSG_FLOW_UNINITED
+ || st->state == MSG_FLOW_FINISHED) {
+ if (st->state == MSG_FLOW_UNINITED) {
+ st->hand_state = TLS_ST_BEFORE;
+ st->request_state = TLS_ST_BEFORE;
+ }
+
+ s->server = server;
+ if (cb != NULL) {
+ if (SSL_IS_FIRST_HANDSHAKE(s) || !SSL_IS_TLS13(s))
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
+ }
+
+ /*
+ * Fatal errors in this block don't send an alert because we have
+ * failed to even initialise properly. Sending an alert is probably
+ * doomed to failure.
+ */
+
+ if (SSL_IS_DTLS(s)) {
+ if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
+ (server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+ } else {
+ if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+ }
+
+ if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+
+ if (s->init_buf == NULL) {
+ if ((buf = BUF_MEM_new()) == NULL) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+ if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+ s->init_buf = buf;
+ buf = NULL;
+ }
+
+ if (!ssl3_setup_buffers(s)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+ s->init_num = 0;
+
+ /*
+ * Should have been reset by tls_process_finished, too.
+ */
+ s->s3->change_cipher_spec = 0;
+
+ /*
+ * Ok, we now need to push on a buffering BIO ...but not with
+ * SCTP
+ */
+#ifndef OPENSSL_NO_SCTP
+ if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
+#endif
+ if (!ssl_init_wbio_buffer(s)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ goto end;
+ }
+
+ if ((SSL_in_before(s))
+ || s->renegotiate) {
+ if (!tls_setup_handshake(s)) {
+ /* SSLfatal() already called */
+ goto end;
+ }
+
+ if (SSL_IS_FIRST_HANDSHAKE(s))
+ st->read_state_first_init = 1;
+ }
+
+ st->state = MSG_FLOW_WRITING;
+ init_write_state_machine(s);
+ }
+
+ while (st->state != MSG_FLOW_FINISHED) {
+ if (st->state == MSG_FLOW_READING) {
+ ssret = read_state_machine(s);
+ if (ssret == SUB_STATE_FINISHED) {
+ st->state = MSG_FLOW_WRITING;
+ init_write_state_machine(s);
+ } else {
+ /* NBIO or error */
+ goto end;
+ }
+ } else if (st->state == MSG_FLOW_WRITING) {
+ ssret = write_state_machine(s);
+ if (ssret == SUB_STATE_FINISHED) {
+ st->state = MSG_FLOW_READING;
+ init_read_state_machine(s);
+ } else if (ssret == SUB_STATE_END_HANDSHAKE) {
+ st->state = MSG_FLOW_FINISHED;
+ } else {
+ /* NBIO or error */
+ goto end;
+ }
+ } else {
+ /* Error */
+ check_fatal(s, SSL_F_STATE_MACHINE);
+ SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ goto end;
+ }
+ }
+
+ ret = 1;
+
+ end:
+ st->in_handshake--;
+
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ /*
+ * Notify SCTP BIO socket to leave handshake mode and allow stream
+ * identifier other than 0.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
+ st->in_handshake, NULL);
+ }
+#endif
+
+ BUF_MEM_free(buf);
+ if (cb != NULL) {
+ if (server)
+ cb(s, SSL_CB_ACCEPT_EXIT, ret);
+ else
+ cb(s, SSL_CB_CONNECT_EXIT, ret);
+ }
+ return ret;
+}
+
+/*
+ * Initialise the MSG_FLOW_READING sub-state machine
+ */
+static void init_read_state_machine(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ st->read_state = READ_STATE_HEADER;
+}
+
+static int grow_init_buf(SSL *s, size_t size) {
+
+ size_t msg_offset = (char *)s->init_msg - s->init_buf->data;
+
+ if (!BUF_MEM_grow_clean(s->init_buf, (int)size))
+ return 0;
+
+ if (size < msg_offset)
+ return 0;
+
+ s->init_msg = s->init_buf->data + msg_offset;
+
+ return 1;
+}
+
+/*
+ * This function implements the sub-state machine when the message flow is in
+ * MSG_FLOW_READING. The valid sub-states and transitions are:
+ *
+ * READ_STATE_HEADER <--+<-------------+
+ * | | |
+ * v | |
+ * READ_STATE_BODY -----+-->READ_STATE_POST_PROCESS
+ * | |
+ * +----------------------------+
+ * v
+ * [SUB_STATE_FINISHED]
+ *
+ * READ_STATE_HEADER has the responsibility for reading in the message header
+ * and transitioning the state of the handshake state machine.
+ *
+ * READ_STATE_BODY reads in the rest of the message and then subsequently
+ * processes it.
+ *
+ * READ_STATE_POST_PROCESS is an optional step that may occur if some post
+ * processing activity performed on the message may block.
+ *
+ * Any of the above states could result in an NBIO event occurring in which case
+ * control returns to the calling application. When this function is recalled we
+ * will resume in the same state where we left off.
+ */
+static SUB_STATE_RETURN read_state_machine(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+ int ret, mt;
+ size_t len = 0;
+ int (*transition) (SSL *s, int mt);
+ PACKET pkt;
+ MSG_PROCESS_RETURN(*process_message) (SSL *s, PACKET *pkt);
+ WORK_STATE(*post_process_message) (SSL *s, WORK_STATE wst);
+ size_t (*max_message_size) (SSL *s);
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+
+ cb = get_callback(s);
+
+ if (s->server) {
+ transition = ossl_statem_server_read_transition;
+ process_message = ossl_statem_server_process_message;
+ max_message_size = ossl_statem_server_max_message_size;
+ post_process_message = ossl_statem_server_post_process_message;
+ } else {
+ transition = ossl_statem_client_read_transition;
+ process_message = ossl_statem_client_process_message;
+ max_message_size = ossl_statem_client_max_message_size;
+ post_process_message = ossl_statem_client_post_process_message;
+ }
+
+ if (st->read_state_first_init) {
+ s->first_packet = 1;
+ st->read_state_first_init = 0;
+ }
+
+ while (1) {
+ switch (st->read_state) {
+ case READ_STATE_HEADER:
+ /* Get the state the peer wants to move to */
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * In DTLS we get the whole message in one go - header and body
+ */
+ ret = dtls_get_message(s, &mt, &len);
+ } else {
+ ret = tls_get_message_header(s, &mt);
+ }
+
+ if (ret == 0) {
+ /* Could be non-blocking IO */
+ return SUB_STATE_ERROR;
+ }
+
+ if (cb != NULL) {
+ /* Notify callback of an impending state change */
+ if (s->server)
+ cb(s, SSL_CB_ACCEPT_LOOP, 1);
+ else
+ cb(s, SSL_CB_CONNECT_LOOP, 1);
+ }
+ /*
+ * Validate that we are allowed to move to the new state and move
+ * to that state if so
+ */
+ if (!transition(s, mt))
+ return SUB_STATE_ERROR;
+
+ if (s->s3->tmp.message_size > max_message_size(s)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
+ SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return SUB_STATE_ERROR;
+ }
+
+ /* dtls_get_message already did this */
+ if (!SSL_IS_DTLS(s)
+ && s->s3->tmp.message_size > 0
+ && !grow_init_buf(s, s->s3->tmp.message_size
+ + SSL3_HM_HEADER_LENGTH)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
+ ERR_R_BUF_LIB);
+ return SUB_STATE_ERROR;
+ }
+
+ st->read_state = READ_STATE_BODY;
+ /* Fall through */
+
+ case READ_STATE_BODY:
+ if (!SSL_IS_DTLS(s)) {
+ /* We already got this above for DTLS */
+ ret = tls_get_message_body(s, &len);
+ if (ret == 0) {
+ /* Could be non-blocking IO */
+ return SUB_STATE_ERROR;
+ }
+ }
+
+ s->first_packet = 0;
+ if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ return SUB_STATE_ERROR;
+ }
+ ret = process_message(s, &pkt);
+
+ /* Discard the packet data */
+ s->init_num = 0;
+
+ switch (ret) {
+ case MSG_PROCESS_ERROR:
+ check_fatal(s, SSL_F_READ_STATE_MACHINE);
+ return SUB_STATE_ERROR;
+
+ case MSG_PROCESS_FINISHED_READING:
+ if (SSL_IS_DTLS(s)) {
+ dtls1_stop_timer(s);
+ }
+ return SUB_STATE_FINISHED;
+
+ case MSG_PROCESS_CONTINUE_PROCESSING:
+ st->read_state = READ_STATE_POST_PROCESS;
+ st->read_state_work = WORK_MORE_A;
+ break;
+
+ default:
+ st->read_state = READ_STATE_HEADER;
+ break;
+ }
+ break;
+
+ case READ_STATE_POST_PROCESS:
+ st->read_state_work = post_process_message(s, st->read_state_work);
+ switch (st->read_state_work) {
+ case WORK_ERROR:
+ check_fatal(s, SSL_F_READ_STATE_MACHINE);
+ /* Fall through */
+ case WORK_MORE_A:
+ case WORK_MORE_B:
+ case WORK_MORE_C:
+ return SUB_STATE_ERROR;
+
+ case WORK_FINISHED_CONTINUE:
+ st->read_state = READ_STATE_HEADER;
+ break;
+
+ case WORK_FINISHED_STOP:
+ if (SSL_IS_DTLS(s)) {
+ dtls1_stop_timer(s);
+ }
+ return SUB_STATE_FINISHED;
+ }
+ break;
+
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ return SUB_STATE_ERROR;
+ }
+ }
+}
+
+/*
+ * Send a previously constructed message to the peer.
+ */
+static int statem_do_write(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ if (st->hand_state == TLS_ST_CW_CHANGE
+ || st->hand_state == TLS_ST_SW_CHANGE) {
+ if (SSL_IS_DTLS(s))
+ return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
+ else
+ return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
+ } else {
+ return ssl_do_write(s);
+ }
+}
+
+/*
+ * Initialise the MSG_FLOW_WRITING sub-state machine
+ */
+static void init_write_state_machine(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ st->write_state = WRITE_STATE_TRANSITION;
+}
+
+/*
+ * This function implements the sub-state machine when the message flow is in
+ * MSG_FLOW_WRITING. The valid sub-states and transitions are:
+ *
+ * +-> WRITE_STATE_TRANSITION ------> [SUB_STATE_FINISHED]
+ * | |
+ * | v
+ * | WRITE_STATE_PRE_WORK -----> [SUB_STATE_END_HANDSHAKE]
+ * | |
+ * | v
+ * | WRITE_STATE_SEND
+ * | |
+ * | v
+ * | WRITE_STATE_POST_WORK
+ * | |
+ * +-------------+
+ *
+ * WRITE_STATE_TRANSITION transitions the state of the handshake state machine
+
+ * WRITE_STATE_PRE_WORK performs any work necessary to prepare the later
+ * sending of the message. This could result in an NBIO event occurring in
+ * which case control returns to the calling application. When this function
+ * is recalled we will resume in the same state where we left off.
+ *
+ * WRITE_STATE_SEND sends the message and performs any work to be done after
+ * sending.
+ *
+ * WRITE_STATE_POST_WORK performs any work necessary after the sending of the
+ * message has been completed. As for WRITE_STATE_PRE_WORK this could also
+ * result in an NBIO event.
+ */
+static SUB_STATE_RETURN write_state_machine(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+ int ret;
+ WRITE_TRAN(*transition) (SSL *s);
+ WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst);
+ WORK_STATE(*post_work) (SSL *s, WORK_STATE wst);
+ int (*get_construct_message_f) (SSL *s, WPACKET *pkt,
+ int (**confunc) (SSL *s, WPACKET *pkt),
+ int *mt);
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ int (*confunc) (SSL *s, WPACKET *pkt);
+ int mt;
+ WPACKET pkt;
+
+ cb = get_callback(s);
+
+ if (s->server) {
+ transition = ossl_statem_server_write_transition;
+ pre_work = ossl_statem_server_pre_work;
+ post_work = ossl_statem_server_post_work;
+ get_construct_message_f = ossl_statem_server_construct_message;
+ } else {
+ transition = ossl_statem_client_write_transition;
+ pre_work = ossl_statem_client_pre_work;
+ post_work = ossl_statem_client_post_work;
+ get_construct_message_f = ossl_statem_client_construct_message;
+ }
+
+ while (1) {
+ switch (st->write_state) {
+ case WRITE_STATE_TRANSITION:
+ if (cb != NULL) {
+ /* Notify callback of an impending state change */
+ if (s->server)
+ cb(s, SSL_CB_ACCEPT_LOOP, 1);
+ else
+ cb(s, SSL_CB_CONNECT_LOOP, 1);
+ }
+ switch (transition(s)) {
+ case WRITE_TRAN_CONTINUE:
+ st->write_state = WRITE_STATE_PRE_WORK;
+ st->write_state_work = WORK_MORE_A;
+ break;
+
+ case WRITE_TRAN_FINISHED:
+ return SUB_STATE_FINISHED;
+ break;
+
+ case WRITE_TRAN_ERROR:
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ return SUB_STATE_ERROR;
+ }
+ break;
+
+ case WRITE_STATE_PRE_WORK:
+ switch (st->write_state_work = pre_work(s, st->write_state_work)) {
+ case WORK_ERROR:
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ /* Fall through */
+ case WORK_MORE_A:
+ case WORK_MORE_B:
+ case WORK_MORE_C:
+ return SUB_STATE_ERROR;
+
+ case WORK_FINISHED_CONTINUE:
+ st->write_state = WRITE_STATE_SEND;
+ break;
+
+ case WORK_FINISHED_STOP:
+ return SUB_STATE_END_HANDSHAKE;
+ }
+ if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
+ /* SSLfatal() already called */
+ return SUB_STATE_ERROR;
+ }
+ if (mt == SSL3_MT_DUMMY) {
+ /* Skip construction and sending. This isn't a "real" state */
+ st->write_state = WRITE_STATE_POST_WORK;
+ st->write_state_work = WORK_MORE_A;
+ break;
+ }
+ if (!WPACKET_init(&pkt, s->init_buf)
+ || !ssl_set_handshake_header(s, &pkt, mt)) {
+ WPACKET_cleanup(&pkt);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ return SUB_STATE_ERROR;
+ }
+ if (confunc != NULL && !confunc(s, &pkt)) {
+ WPACKET_cleanup(&pkt);
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ return SUB_STATE_ERROR;
+ }
+ if (!ssl_close_construct_packet(s, &pkt, mt)
+ || !WPACKET_finish(&pkt)) {
+ WPACKET_cleanup(&pkt);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ return SUB_STATE_ERROR;
+ }
+
+ /* Fall through */
+
+ case WRITE_STATE_SEND:
+ if (SSL_IS_DTLS(s) && st->use_timer) {
+ dtls1_start_timer(s);
+ }
+ ret = statem_do_write(s);
+ if (ret <= 0) {
+ return SUB_STATE_ERROR;
+ }
+ st->write_state = WRITE_STATE_POST_WORK;
+ st->write_state_work = WORK_MORE_A;
+ /* Fall through */
+
+ case WRITE_STATE_POST_WORK:
+ switch (st->write_state_work = post_work(s, st->write_state_work)) {
+ case WORK_ERROR:
+ check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+ /* Fall through */
+ case WORK_MORE_A:
+ case WORK_MORE_B:
+ case WORK_MORE_C:
+ return SUB_STATE_ERROR;
+
+ case WORK_FINISHED_CONTINUE:
+ st->write_state = WRITE_STATE_TRANSITION;
+ break;
+
+ case WORK_FINISHED_STOP:
+ return SUB_STATE_END_HANDSHAKE;
+ }
+ break;
+
+ default:
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
+ ERR_R_INTERNAL_ERROR);
+ return SUB_STATE_ERROR;
+ }
+ }
+}
+
+/*
+ * Flush the write BIO
+ */
+int statem_flush(SSL *s)
+{
+ s->rwstate = SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0) {
+ return 0;
+ }
+ s->rwstate = SSL_NOTHING;
+
+ return 1;
+}
+
+/*
+ * Called by the record layer to determine whether application data is
+ * allowed to be received in the current handshake state or not.
+ *
+ * Return values are:
+ * 1: Yes (application data allowed)
+ * 0: No (application data not allowed)
+ */
+int ossl_statem_app_data_allowed(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ if (st->state == MSG_FLOW_UNINITED)
+ return 0;
+
+ if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0))
+ return 0;
+
+ if (s->server) {
+ /*
+ * If we're a server and we haven't got as far as writing our
+ * ServerHello yet then we allow app data
+ */
+ if (st->hand_state == TLS_ST_BEFORE
+ || st->hand_state == TLS_ST_SR_CLNT_HELLO)
+ return 1;
+ } else {
+ /*
+ * If we're a client and we haven't read the ServerHello yet then we
+ * allow app data
+ */
+ if (st->hand_state == TLS_ST_CW_CLNT_HELLO)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * This function returns 1 if TLS exporter is ready to export keying
+ * material, or 0 if otherwise.
+ */
+int ossl_statem_export_allowed(SSL *s)
+{
+ return s->s3->previous_server_finished_len != 0
+ && s->statem.hand_state != TLS_ST_SW_FINISHED;
+}
+
+/*
+ * Return 1 if early TLS exporter is ready to export keying material,
+ * or 0 if otherwise.
+ */
+int ossl_statem_export_early_allowed(SSL *s)
+{
+ /*
+ * The early exporter secret is only present on the server if we
+ * have accepted early_data. It is present on the client as long
+ * as we have sent early_data.
+ */
+ return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
+ || (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT);
+}
diff --git a/contrib/libs/openssl/ssl/statem/statem.h b/contrib/libs/openssl/ssl/statem/statem.h
index 144d930fc7..aa24b03fd5 100644
--- a/contrib/libs/openssl/ssl/statem/statem.h
+++ b/contrib/libs/openssl/ssl/statem/statem.h
@@ -1,157 +1,157 @@
-/*
- * Copyright 2015-2018 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
- */
-
-/*****************************************************************************
- * *
- * These enums should be considered PRIVATE to the state machine. No *
- * non-state machine code should need to use these *
- * *
- *****************************************************************************/
-/*
- * Valid return codes used for functions performing work prior to or after
- * sending or receiving a message
- */
-typedef enum {
- /* Something went wrong */
- WORK_ERROR,
- /* We're done working and there shouldn't be anything else to do after */
- WORK_FINISHED_STOP,
- /* We're done working move onto the next thing */
- WORK_FINISHED_CONTINUE,
- /* We're working on phase A */
- WORK_MORE_A,
- /* We're working on phase B */
- WORK_MORE_B,
- /* We're working on phase C */
- WORK_MORE_C
-} WORK_STATE;
-
-/* Write transition return codes */
-typedef enum {
- /* Something went wrong */
- WRITE_TRAN_ERROR,
- /* A transition was successfully completed and we should continue */
- WRITE_TRAN_CONTINUE,
- /* There is no more write work to be done */
- WRITE_TRAN_FINISHED
-} WRITE_TRAN;
-
-/* Message flow states */
-typedef enum {
- /* No handshake in progress */
- MSG_FLOW_UNINITED,
- /* A permanent error with this connection */
- MSG_FLOW_ERROR,
- /* We are reading messages */
- MSG_FLOW_READING,
- /* We are writing messages */
- MSG_FLOW_WRITING,
- /* Handshake has finished */
- MSG_FLOW_FINISHED
-} MSG_FLOW_STATE;
-
-/* Read states */
-typedef enum {
- READ_STATE_HEADER,
- READ_STATE_BODY,
- READ_STATE_POST_PROCESS
-} READ_STATE;
-
-/* Write states */
-typedef enum {
- WRITE_STATE_TRANSITION,
- WRITE_STATE_PRE_WORK,
- WRITE_STATE_SEND,
- WRITE_STATE_POST_WORK
-} WRITE_STATE;
-
-typedef enum {
- /* The enc_write_ctx can be used normally */
- ENC_WRITE_STATE_VALID,
- /* The enc_write_ctx cannot be used */
- ENC_WRITE_STATE_INVALID,
- /* Write alerts in plaintext, but otherwise use the enc_write_ctx */
- ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
-} ENC_WRITE_STATES;
-
-typedef enum {
- /* The enc_read_ctx can be used normally */
- ENC_READ_STATE_VALID,
- /* We may receive encrypted or plaintext alerts */
- ENC_READ_STATE_ALLOW_PLAIN_ALERTS
-} ENC_READ_STATES;
-
-/*****************************************************************************
- * *
- * This structure should be considered "opaque" to anything outside of the *
- * state machine. No non-state machine code should be accessing the members *
- * of this structure. *
- * *
- *****************************************************************************/
-
-struct ossl_statem_st {
- MSG_FLOW_STATE state;
- WRITE_STATE write_state;
- WORK_STATE write_state_work;
- READ_STATE read_state;
- WORK_STATE read_state_work;
- OSSL_HANDSHAKE_STATE hand_state;
- /* The handshake state requested by an API call (e.g. HelloRequest) */
- OSSL_HANDSHAKE_STATE request_state;
- int in_init;
- int read_state_first_init;
- /* true when we are actually in SSL_accept() or SSL_connect() */
- int in_handshake;
- /*
- * True when are processing a "real" handshake that needs cleaning up (not
- * just a HelloRequest or similar).
- */
- int cleanuphand;
- /* Should we skip the CertificateVerify message? */
- unsigned int no_cert_verify;
- int use_timer;
- ENC_WRITE_STATES enc_write_state;
- ENC_READ_STATES enc_read_state;
-};
-typedef struct ossl_statem_st OSSL_STATEM;
-
-/*****************************************************************************
- * *
- * The following macros/functions represent the libssl internal API to the *
- * state machine. Any libssl code may call these functions/macros *
- * *
- *****************************************************************************/
-
-__owur int ossl_statem_accept(SSL *s);
-__owur int ossl_statem_connect(SSL *s);
-void ossl_statem_clear(SSL *s);
-void ossl_statem_set_renegotiate(SSL *s);
-void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
- int line);
-# define SSL_AD_NO_ALERT -1
-# ifndef OPENSSL_NO_ERR
-# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), \
- OPENSSL_FILE, OPENSSL_LINE)
-# else
-# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), NULL, 0)
-# endif
-
-int ossl_statem_in_error(const SSL *s);
-void ossl_statem_set_in_init(SSL *s, int init);
-int ossl_statem_get_in_handshake(SSL *s);
-void ossl_statem_set_in_handshake(SSL *s, int inhand);
-__owur int ossl_statem_skip_early_data(SSL *s);
-void ossl_statem_check_finish_init(SSL *s, int send);
-void ossl_statem_set_hello_verify_done(SSL *s);
-__owur int ossl_statem_app_data_allowed(SSL *s);
-__owur int ossl_statem_export_allowed(SSL *s);
-__owur int ossl_statem_export_early_allowed(SSL *s);
-
-/* Flush the write BIO */
-int statem_flush(SSL *s);
+/*
+ * Copyright 2015-2018 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
+ */
+
+/*****************************************************************************
+ * *
+ * These enums should be considered PRIVATE to the state machine. No *
+ * non-state machine code should need to use these *
+ * *
+ *****************************************************************************/
+/*
+ * Valid return codes used for functions performing work prior to or after
+ * sending or receiving a message
+ */
+typedef enum {
+ /* Something went wrong */
+ WORK_ERROR,
+ /* We're done working and there shouldn't be anything else to do after */
+ WORK_FINISHED_STOP,
+ /* We're done working move onto the next thing */
+ WORK_FINISHED_CONTINUE,
+ /* We're working on phase A */
+ WORK_MORE_A,
+ /* We're working on phase B */
+ WORK_MORE_B,
+ /* We're working on phase C */
+ WORK_MORE_C
+} WORK_STATE;
+
+/* Write transition return codes */
+typedef enum {
+ /* Something went wrong */
+ WRITE_TRAN_ERROR,
+ /* A transition was successfully completed and we should continue */
+ WRITE_TRAN_CONTINUE,
+ /* There is no more write work to be done */
+ WRITE_TRAN_FINISHED
+} WRITE_TRAN;
+
+/* Message flow states */
+typedef enum {
+ /* No handshake in progress */
+ MSG_FLOW_UNINITED,
+ /* A permanent error with this connection */
+ MSG_FLOW_ERROR,
+ /* We are reading messages */
+ MSG_FLOW_READING,
+ /* We are writing messages */
+ MSG_FLOW_WRITING,
+ /* Handshake has finished */
+ MSG_FLOW_FINISHED
+} MSG_FLOW_STATE;
+
+/* Read states */
+typedef enum {
+ READ_STATE_HEADER,
+ READ_STATE_BODY,
+ READ_STATE_POST_PROCESS
+} READ_STATE;
+
+/* Write states */
+typedef enum {
+ WRITE_STATE_TRANSITION,
+ WRITE_STATE_PRE_WORK,
+ WRITE_STATE_SEND,
+ WRITE_STATE_POST_WORK
+} WRITE_STATE;
+
+typedef enum {
+ /* The enc_write_ctx can be used normally */
+ ENC_WRITE_STATE_VALID,
+ /* The enc_write_ctx cannot be used */
+ ENC_WRITE_STATE_INVALID,
+ /* Write alerts in plaintext, but otherwise use the enc_write_ctx */
+ ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
+} ENC_WRITE_STATES;
+
+typedef enum {
+ /* The enc_read_ctx can be used normally */
+ ENC_READ_STATE_VALID,
+ /* We may receive encrypted or plaintext alerts */
+ ENC_READ_STATE_ALLOW_PLAIN_ALERTS
+} ENC_READ_STATES;
+
+/*****************************************************************************
+ * *
+ * This structure should be considered "opaque" to anything outside of the *
+ * state machine. No non-state machine code should be accessing the members *
+ * of this structure. *
+ * *
+ *****************************************************************************/
+
+struct ossl_statem_st {
+ MSG_FLOW_STATE state;
+ WRITE_STATE write_state;
+ WORK_STATE write_state_work;
+ READ_STATE read_state;
+ WORK_STATE read_state_work;
+ OSSL_HANDSHAKE_STATE hand_state;
+ /* The handshake state requested by an API call (e.g. HelloRequest) */
+ OSSL_HANDSHAKE_STATE request_state;
+ int in_init;
+ int read_state_first_init;
+ /* true when we are actually in SSL_accept() or SSL_connect() */
+ int in_handshake;
+ /*
+ * True when are processing a "real" handshake that needs cleaning up (not
+ * just a HelloRequest or similar).
+ */
+ int cleanuphand;
+ /* Should we skip the CertificateVerify message? */
+ unsigned int no_cert_verify;
+ int use_timer;
+ ENC_WRITE_STATES enc_write_state;
+ ENC_READ_STATES enc_read_state;
+};
+typedef struct ossl_statem_st OSSL_STATEM;
+
+/*****************************************************************************
+ * *
+ * The following macros/functions represent the libssl internal API to the *
+ * state machine. Any libssl code may call these functions/macros *
+ * *
+ *****************************************************************************/
+
+__owur int ossl_statem_accept(SSL *s);
+__owur int ossl_statem_connect(SSL *s);
+void ossl_statem_clear(SSL *s);
+void ossl_statem_set_renegotiate(SSL *s);
+void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
+ int line);
+# define SSL_AD_NO_ALERT -1
+# ifndef OPENSSL_NO_ERR
+# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), \
+ OPENSSL_FILE, OPENSSL_LINE)
+# else
+# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), NULL, 0)
+# endif
+
+int ossl_statem_in_error(const SSL *s);
+void ossl_statem_set_in_init(SSL *s, int init);
+int ossl_statem_get_in_handshake(SSL *s);
+void ossl_statem_set_in_handshake(SSL *s, int inhand);
+__owur int ossl_statem_skip_early_data(SSL *s);
+void ossl_statem_check_finish_init(SSL *s, int send);
+void ossl_statem_set_hello_verify_done(SSL *s);
+__owur int ossl_statem_app_data_allowed(SSL *s);
+__owur int ossl_statem_export_allowed(SSL *s);
+__owur int ossl_statem_export_early_allowed(SSL *s);
+
+/* Flush the write BIO */
+int statem_flush(SSL *s);
diff --git a/contrib/libs/openssl/ssl/statem/statem_clnt.c b/contrib/libs/openssl/ssl/statem/statem_clnt.c
index d1a3969812..be66b19fb4 100644
--- a/contrib/libs/openssl/ssl/statem/statem_clnt.c
+++ b/contrib/libs/openssl/ssl/statem/statem_clnt.c
@@ -1,2157 +1,2157 @@
-/*
+/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
- * Copyright 2005 Nokia. 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 <stdio.h>
-#include <time.h>
-#include <assert.h>
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ * Copyright 2005 Nokia. 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 <stdio.h>
+#include <time.h>
+#include <assert.h>
#include "../ssl_local.h"
#include "statem_local.h"
-#include <openssl/buffer.h>
-#include <openssl/rand.h>
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-#include <openssl/md5.h>
-#include <openssl/dh.h>
-#include <openssl/bn.h>
-#include <openssl/engine.h>
-#include <internal/cryptlib.h>
-
-static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
-static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
-
-static ossl_inline int cert_req_allowed(SSL *s);
-static int key_exchange_expected(SSL *s);
-static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
- WPACKET *pkt);
-
-/*
- * Is a CertificateRequest message allowed at the moment or not?
- *
- * Return values are:
- * 1: Yes
- * 0: No
- */
-static ossl_inline int cert_req_allowed(SSL *s)
-{
- /* TLS does not like anon-DH with client cert */
- if ((s->version > SSL3_VERSION
- && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
- || (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK)))
- return 0;
-
- return 1;
-}
-
-/*
- * Should we expect the ServerKeyExchange message or not?
- *
- * Return values are:
- * 1: Yes
- * 0: No
- */
-static int key_exchange_expected(SSL *s)
-{
- long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-
- /*
- * Can't skip server key exchange if this is an ephemeral
- * ciphersuite or for SRP
- */
- if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK
- | SSL_kSRP)) {
- return 1;
- }
-
- return 0;
-}
-
-/*
- * ossl_statem_client_read_transition() encapsulates the logic for the allowed
- * handshake state transitions when a TLS1.3 client is reading messages from the
- * server. The message type that the server has sent is provided in |mt|. The
- * current state is in |s->statem.hand_state|.
- *
- * Return values are 1 for success (transition allowed) and 0 on error
- * (transition not allowed)
- */
-static int ossl_statem_client13_read_transition(SSL *s, int mt)
-{
- OSSL_STATEM *st = &s->statem;
-
- /*
- * Note: There is no case for TLS_ST_CW_CLNT_HELLO, because we haven't
- * yet negotiated TLSv1.3 at that point so that is handled by
- * ossl_statem_client_read_transition()
- */
-
- switch (st->hand_state) {
- default:
- break;
-
- case TLS_ST_CW_CLNT_HELLO:
- /*
- * This must a ClientHello following a HelloRetryRequest, so the only
- * thing we can get now is a ServerHello.
- */
- if (mt == SSL3_MT_SERVER_HELLO) {
- st->hand_state = TLS_ST_CR_SRVR_HELLO;
- return 1;
- }
- break;
-
- case TLS_ST_CR_SRVR_HELLO:
- if (mt == SSL3_MT_ENCRYPTED_EXTENSIONS) {
- st->hand_state = TLS_ST_CR_ENCRYPTED_EXTENSIONS;
- return 1;
- }
- break;
-
- case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
- if (s->hit) {
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_CR_FINISHED;
- return 1;
- }
- } else {
- if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
- st->hand_state = TLS_ST_CR_CERT_REQ;
- return 1;
- }
- if (mt == SSL3_MT_CERTIFICATE) {
- st->hand_state = TLS_ST_CR_CERT;
- return 1;
- }
- }
- break;
-
- case TLS_ST_CR_CERT_REQ:
- if (mt == SSL3_MT_CERTIFICATE) {
- st->hand_state = TLS_ST_CR_CERT;
- return 1;
- }
- break;
-
- case TLS_ST_CR_CERT:
- if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
- st->hand_state = TLS_ST_CR_CERT_VRFY;
- return 1;
- }
- break;
-
- case TLS_ST_CR_CERT_VRFY:
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_CR_FINISHED;
- return 1;
- }
- break;
-
- case TLS_ST_OK:
- if (mt == SSL3_MT_NEWSESSION_TICKET) {
- st->hand_state = TLS_ST_CR_SESSION_TICKET;
- return 1;
- }
- if (mt == SSL3_MT_KEY_UPDATE) {
- st->hand_state = TLS_ST_CR_KEY_UPDATE;
- return 1;
- }
- if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
-#if DTLS_MAX_VERSION != DTLS1_2_VERSION
-# error TODO(DTLS1.3): Restore digest for PHA before adding message.
-#endif
- if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) {
- s->post_handshake_auth = SSL_PHA_REQUESTED;
- /*
- * In TLS, this is called before the message is added to the
- * digest. In DTLS, this is expected to be called after adding
- * to the digest. Either move the digest restore, or add the
- * message here after the swap, or do it after the clientFinished?
- */
- if (!tls13_restore_handshake_digest_for_pha(s)) {
- /* SSLfatal() already called */
- return 0;
- }
- st->hand_state = TLS_ST_CR_CERT_REQ;
- return 1;
- }
- }
- break;
- }
-
- /* No valid transition found */
- return 0;
-}
-
-/*
- * ossl_statem_client_read_transition() encapsulates the logic for the allowed
- * handshake state transitions when the client is reading messages from the
- * server. The message type that the server has sent is provided in |mt|. The
- * current state is in |s->statem.hand_state|.
- *
- * Return values are 1 for success (transition allowed) and 0 on error
- * (transition not allowed)
- */
-int ossl_statem_client_read_transition(SSL *s, int mt)
-{
- OSSL_STATEM *st = &s->statem;
- int ske_expected;
-
- /*
- * Note that after writing the first ClientHello we don't know what version
- * we are going to negotiate yet, so we don't take this branch until later.
- */
- if (SSL_IS_TLS13(s)) {
- if (!ossl_statem_client13_read_transition(s, mt))
- goto err;
- return 1;
- }
-
- switch (st->hand_state) {
- default:
- break;
-
- case TLS_ST_CW_CLNT_HELLO:
- if (mt == SSL3_MT_SERVER_HELLO) {
- st->hand_state = TLS_ST_CR_SRVR_HELLO;
- return 1;
- }
-
- if (SSL_IS_DTLS(s)) {
- if (mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
- st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
- return 1;
- }
- }
- break;
-
- case TLS_ST_EARLY_DATA:
- /*
- * We've not actually selected TLSv1.3 yet, but we have sent early
- * data. The only thing allowed now is a ServerHello or a
- * HelloRetryRequest.
- */
- if (mt == SSL3_MT_SERVER_HELLO) {
- st->hand_state = TLS_ST_CR_SRVR_HELLO;
- return 1;
- }
- break;
-
- case TLS_ST_CR_SRVR_HELLO:
- if (s->hit) {
- if (s->ext.ticket_expected) {
- if (mt == SSL3_MT_NEWSESSION_TICKET) {
- st->hand_state = TLS_ST_CR_SESSION_TICKET;
- return 1;
- }
- } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- st->hand_state = TLS_ST_CR_CHANGE;
- return 1;
- }
- } else {
- if (SSL_IS_DTLS(s) && mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
- st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
- return 1;
- } else if (s->version >= TLS1_VERSION
- && s->ext.session_secret_cb != NULL
- && s->session->ext.tick != NULL
- && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- /*
- * Normally, we can tell if the server is resuming the session
- * from the session ID. EAP-FAST (RFC 4851), however, relies on
- * the next server message after the ServerHello to determine if
- * the server is resuming.
- */
- s->hit = 1;
- st->hand_state = TLS_ST_CR_CHANGE;
- return 1;
- } else if (!(s->s3->tmp.new_cipher->algorithm_auth
- & (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
- if (mt == SSL3_MT_CERTIFICATE) {
- st->hand_state = TLS_ST_CR_CERT;
- return 1;
- }
- } else {
- ske_expected = key_exchange_expected(s);
- /* SKE is optional for some PSK ciphersuites */
- if (ske_expected
- || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
- && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
- if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
- st->hand_state = TLS_ST_CR_KEY_EXCH;
- return 1;
- }
- } else if (mt == SSL3_MT_CERTIFICATE_REQUEST
- && cert_req_allowed(s)) {
- st->hand_state = TLS_ST_CR_CERT_REQ;
- return 1;
- } else if (mt == SSL3_MT_SERVER_DONE) {
- st->hand_state = TLS_ST_CR_SRVR_DONE;
- return 1;
- }
- }
- }
- break;
-
- case TLS_ST_CR_CERT:
- /*
- * The CertificateStatus message is optional even if
- * |ext.status_expected| is set
- */
- if (s->ext.status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) {
- st->hand_state = TLS_ST_CR_CERT_STATUS;
- return 1;
- }
- /* Fall through */
-
- case TLS_ST_CR_CERT_STATUS:
- ske_expected = key_exchange_expected(s);
- /* SKE is optional for some PSK ciphersuites */
- if (ske_expected || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
- && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
- if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
- st->hand_state = TLS_ST_CR_KEY_EXCH;
- return 1;
- }
- goto err;
- }
- /* Fall through */
-
- case TLS_ST_CR_KEY_EXCH:
- if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
- if (cert_req_allowed(s)) {
- st->hand_state = TLS_ST_CR_CERT_REQ;
- return 1;
- }
- goto err;
- }
- /* Fall through */
-
- case TLS_ST_CR_CERT_REQ:
- if (mt == SSL3_MT_SERVER_DONE) {
- st->hand_state = TLS_ST_CR_SRVR_DONE;
- return 1;
- }
- break;
-
- case TLS_ST_CW_FINISHED:
- if (s->ext.ticket_expected) {
- if (mt == SSL3_MT_NEWSESSION_TICKET) {
- st->hand_state = TLS_ST_CR_SESSION_TICKET;
- return 1;
- }
- } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- st->hand_state = TLS_ST_CR_CHANGE;
- return 1;
- }
- break;
-
- case TLS_ST_CR_SESSION_TICKET:
- if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- st->hand_state = TLS_ST_CR_CHANGE;
- return 1;
- }
- break;
-
- case TLS_ST_CR_CHANGE:
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_CR_FINISHED;
- return 1;
- }
- break;
-
- case TLS_ST_OK:
- if (mt == SSL3_MT_HELLO_REQUEST) {
- st->hand_state = TLS_ST_CR_HELLO_REQ;
- return 1;
- }
- break;
- }
-
- err:
- /* No valid transition found */
- if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- BIO *rbio;
-
- /*
- * CCS messages don't have a message sequence number so this is probably
- * because of an out-of-order CCS. We'll just drop it.
- */
- s->init_num = 0;
- s->rwstate = SSL_READING;
- rbio = SSL_get_rbio(s);
- BIO_clear_retry_flags(rbio);
- BIO_set_retry_read(rbio);
- return 0;
- }
- SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
- SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION,
- SSL_R_UNEXPECTED_MESSAGE);
- return 0;
-}
-
-/*
- * ossl_statem_client13_write_transition() works out what handshake state to
- * move to next when the TLSv1.3 client is writing messages to be sent to the
- * server.
- */
-static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- /*
- * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
- * TLSv1.3 yet at that point. They are handled by
- * ossl_statem_client_write_transition().
- */
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
- return WRITE_TRAN_ERROR;
-
- case TLS_ST_CR_CERT_REQ:
- if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
- st->hand_state = TLS_ST_CW_CERT;
- return WRITE_TRAN_CONTINUE;
- }
- /*
- * We should only get here if we received a CertificateRequest after
- * we already sent close_notify
- */
- if (!ossl_assert((s->shutdown & SSL_SENT_SHUTDOWN) != 0)) {
- /* Shouldn't happen - same as default case */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
- return WRITE_TRAN_ERROR;
- }
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CR_FINISHED:
- if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
- || s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING)
- st->hand_state = TLS_ST_PENDING_EARLY_DATA_END;
- else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
- && s->hello_retry_request == SSL_HRR_NONE)
- st->hand_state = TLS_ST_CW_CHANGE;
- else
- st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
- : TLS_ST_CW_FINISHED;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_PENDING_EARLY_DATA_END:
- if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
- st->hand_state = TLS_ST_CW_END_OF_EARLY_DATA;
- return WRITE_TRAN_CONTINUE;
- }
- /* Fall through */
-
- case TLS_ST_CW_END_OF_EARLY_DATA:
- case TLS_ST_CW_CHANGE:
- st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
- : TLS_ST_CW_FINISHED;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CW_CERT:
- /* If a non-empty Certificate we also send CertificateVerify */
- st->hand_state = (s->s3->tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY
- : TLS_ST_CW_FINISHED;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CW_CERT_VRFY:
- st->hand_state = TLS_ST_CW_FINISHED;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CR_KEY_UPDATE:
- case TLS_ST_CW_KEY_UPDATE:
- case TLS_ST_CR_SESSION_TICKET:
- case TLS_ST_CW_FINISHED:
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_OK:
- if (s->key_update != SSL_KEY_UPDATE_NONE) {
- st->hand_state = TLS_ST_CW_KEY_UPDATE;
- return WRITE_TRAN_CONTINUE;
- }
-
- /* Try to read from the server instead */
- return WRITE_TRAN_FINISHED;
- }
-}
-
-/*
- * ossl_statem_client_write_transition() works out what handshake state to
- * move to next when the client is writing messages to be sent to the server.
- */
-WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- /*
- * Note that immediately before/after a ClientHello we don't know what
- * version we are going to negotiate yet, so we don't take this branch until
- * later
- */
- if (SSL_IS_TLS13(s))
- return ossl_statem_client13_write_transition(s);
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
- return WRITE_TRAN_ERROR;
-
- case TLS_ST_OK:
- if (!s->renegotiate) {
- /*
- * We haven't requested a renegotiation ourselves so we must have
- * received a message from the server. Better read it.
- */
- return WRITE_TRAN_FINISHED;
- }
- /* Renegotiation */
- /* fall thru */
- case TLS_ST_BEFORE:
- st->hand_state = TLS_ST_CW_CLNT_HELLO;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CW_CLNT_HELLO:
- if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
- /*
- * We are assuming this is a TLSv1.3 connection, although we haven't
- * actually selected a version yet.
- */
- if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
- st->hand_state = TLS_ST_CW_CHANGE;
- else
- st->hand_state = TLS_ST_EARLY_DATA;
- return WRITE_TRAN_CONTINUE;
- }
- /*
- * No transition at the end of writing because we don't know what
- * we will be sent
- */
- return WRITE_TRAN_FINISHED;
-
- case TLS_ST_CR_SRVR_HELLO:
- /*
- * We only get here in TLSv1.3. We just received an HRR, so issue a
- * CCS unless middlebox compat mode is off, or we already issued one
- * because we did early data.
- */
- if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
- && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
- st->hand_state = TLS_ST_CW_CHANGE;
- else
- st->hand_state = TLS_ST_CW_CLNT_HELLO;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_EARLY_DATA:
- return WRITE_TRAN_FINISHED;
-
- case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
- st->hand_state = TLS_ST_CW_CLNT_HELLO;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CR_SRVR_DONE:
- if (s->s3->tmp.cert_req)
- st->hand_state = TLS_ST_CW_CERT;
- else
- st->hand_state = TLS_ST_CW_KEY_EXCH;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CW_CERT:
- st->hand_state = TLS_ST_CW_KEY_EXCH;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CW_KEY_EXCH:
- /*
- * For TLS, cert_req is set to 2, so a cert chain of nothing is
- * sent, but no verify packet is sent
- */
- /*
- * XXX: For now, we do not support client authentication in ECDH
- * cipher suites with ECDH (rather than ECDSA) certificates. We
- * need to skip the certificate verify message when client's
- * ECDH public key is sent inside the client certificate.
- */
- if (s->s3->tmp.cert_req == 1) {
- st->hand_state = TLS_ST_CW_CERT_VRFY;
- } else {
- st->hand_state = TLS_ST_CW_CHANGE;
- }
- if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) {
- st->hand_state = TLS_ST_CW_CHANGE;
- }
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CW_CERT_VRFY:
- st->hand_state = TLS_ST_CW_CHANGE;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_CW_CHANGE:
- if (s->hello_retry_request == SSL_HRR_PENDING) {
- st->hand_state = TLS_ST_CW_CLNT_HELLO;
- } else if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
- st->hand_state = TLS_ST_EARLY_DATA;
- } else {
-#if defined(OPENSSL_NO_NEXTPROTONEG)
- st->hand_state = TLS_ST_CW_FINISHED;
-#else
- if (!SSL_IS_DTLS(s) && s->s3->npn_seen)
- st->hand_state = TLS_ST_CW_NEXT_PROTO;
- else
- st->hand_state = TLS_ST_CW_FINISHED;
-#endif
- }
- return WRITE_TRAN_CONTINUE;
-
-#if !defined(OPENSSL_NO_NEXTPROTONEG)
- case TLS_ST_CW_NEXT_PROTO:
- st->hand_state = TLS_ST_CW_FINISHED;
- return WRITE_TRAN_CONTINUE;
-#endif
-
- case TLS_ST_CW_FINISHED:
- if (s->hit) {
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
- } else {
- return WRITE_TRAN_FINISHED;
- }
-
- case TLS_ST_CR_FINISHED:
- if (s->hit) {
- st->hand_state = TLS_ST_CW_CHANGE;
- return WRITE_TRAN_CONTINUE;
- } else {
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
- }
-
- case TLS_ST_CR_HELLO_REQ:
- /*
- * If we can renegotiate now then do so, otherwise wait for a more
- * convenient time.
- */
- if (ssl3_renegotiate_check(s, 1)) {
- if (!tls_setup_handshake(s)) {
- /* SSLfatal() already called */
- return WRITE_TRAN_ERROR;
- }
- st->hand_state = TLS_ST_CW_CLNT_HELLO;
- return WRITE_TRAN_CONTINUE;
- }
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
- }
-}
-
-/*
- * Perform any pre work that needs to be done prior to sending a message from
- * the client to the server.
- */
-WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* No pre work to be done */
- break;
-
- case TLS_ST_CW_CLNT_HELLO:
- s->shutdown = 0;
- if (SSL_IS_DTLS(s)) {
- /* every DTLS ClientHello resets Finished MAC */
- if (!ssl3_init_finished_mac(s)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- }
- break;
-
- case TLS_ST_CW_CHANGE:
- if (SSL_IS_DTLS(s)) {
- if (s->hit) {
- /*
- * We're into the last flight so we don't retransmit these
- * messages unless we need to.
- */
- st->use_timer = 0;
- }
-#ifndef OPENSSL_NO_SCTP
- if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
- /* Calls SSLfatal() as required */
- return dtls_wait_for_dry(s);
- }
-#endif
- }
- break;
-
- case TLS_ST_PENDING_EARLY_DATA_END:
- /*
- * If we've been called by SSL_do_handshake()/SSL_write(), or we did not
- * attempt to write early data before calling SSL_read() then we press
- * on with the handshake. Otherwise we pause here.
- */
- if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING
- || s->early_data_state == SSL_EARLY_DATA_NONE)
- return WORK_FINISHED_CONTINUE;
- /* Fall through */
-
- case TLS_ST_EARLY_DATA:
- return tls_finish_handshake(s, wst, 0, 1);
-
- case TLS_ST_OK:
- /* Calls SSLfatal() as required */
- return tls_finish_handshake(s, wst, 1, 1);
- }
-
- return WORK_FINISHED_CONTINUE;
-}
-
-/*
- * Perform any work that needs to be done after sending a message from the
- * client to the server.
- */
-WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
-{
- OSSL_STATEM *st = &s->statem;
-
- s->init_num = 0;
-
- switch (st->hand_state) {
- default:
- /* No post work to be done */
- break;
-
- case TLS_ST_CW_CLNT_HELLO:
- if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
- && s->max_early_data > 0) {
- /*
- * We haven't selected TLSv1.3 yet so we don't call the change
- * cipher state function associated with the SSL_METHOD. Instead
- * we call tls13_change_cipher_state() directly.
- */
- if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) {
- if (!tls13_change_cipher_state(s,
- SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- }
- /* else we're in compat mode so we delay flushing until after CCS */
- } else if (!statem_flush(s)) {
- return WORK_MORE_A;
- }
-
- if (SSL_IS_DTLS(s)) {
- /* Treat the next message as the first packet */
- s->first_packet = 1;
- }
- break;
-
- case TLS_ST_CW_END_OF_EARLY_DATA:
- /*
- * We set the enc_write_ctx back to NULL because we may end up writing
- * in cleartext again if we get a HelloRetryRequest from the server.
- */
- EVP_CIPHER_CTX_free(s->enc_write_ctx);
- s->enc_write_ctx = NULL;
- break;
-
- case TLS_ST_CW_KEY_EXCH:
- if (tls_client_key_exchange_post_work(s) == 0) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- break;
-
- case TLS_ST_CW_CHANGE:
- if (SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING)
- break;
- if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
- && s->max_early_data > 0) {
- /*
- * We haven't selected TLSv1.3 yet so we don't call the change
- * cipher state function associated with the SSL_METHOD. Instead
- * we call tls13_change_cipher_state() directly.
- */
- if (!tls13_change_cipher_state(s,
- SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
- return WORK_ERROR;
- break;
- }
- s->session->cipher = s->s3->tmp.new_cipher;
-#ifdef OPENSSL_NO_COMP
- s->session->compress_meth = 0;
-#else
- if (s->s3->tmp.new_compression == NULL)
- s->session->compress_meth = 0;
- else
- s->session->compress_meth = s->s3->tmp.new_compression->id;
-#endif
- if (!s->method->ssl3_enc->setup_key_block(s)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
-
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
-
- if (SSL_IS_DTLS(s)) {
-#ifndef OPENSSL_NO_SCTP
- if (s->hit) {
- /*
- * Change to new shared key of SCTP-Auth, will be ignored if
- * no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
- 0, NULL);
- }
-#endif
-
- dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
- }
- break;
-
- case TLS_ST_CW_FINISHED:
-#ifndef OPENSSL_NO_SCTP
- if (wst == WORK_MORE_A && SSL_IS_DTLS(s) && s->hit == 0) {
- /*
- * Change to new shared key of SCTP-Auth, will be ignored if
- * no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
- 0, NULL);
- }
-#endif
- if (statem_flush(s) != 1)
- return WORK_MORE_B;
-
- if (SSL_IS_TLS13(s)) {
- if (!tls13_save_handshake_digest_for_pha(s)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- if (s->post_handshake_auth != SSL_PHA_REQUESTED) {
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- }
- }
- break;
-
- case TLS_ST_CW_KEY_UPDATE:
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
- if (!tls13_update_key(s, 1)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- break;
- }
-
- return WORK_FINISHED_CONTINUE;
-}
-
-/*
- * Get the message construction function and message type for sending from the
- * client
- *
- * Valid return values are:
- * 1: Success
- * 0: Error
- */
-int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
- confunc_f *confunc, int *mt)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE,
- SSL_R_BAD_HANDSHAKE_STATE);
- return 0;
-
- case TLS_ST_CW_CHANGE:
- if (SSL_IS_DTLS(s))
- *confunc = dtls_construct_change_cipher_spec;
- else
- *confunc = tls_construct_change_cipher_spec;
- *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
- break;
-
- case TLS_ST_CW_CLNT_HELLO:
- *confunc = tls_construct_client_hello;
- *mt = SSL3_MT_CLIENT_HELLO;
- break;
-
- case TLS_ST_CW_END_OF_EARLY_DATA:
- *confunc = tls_construct_end_of_early_data;
- *mt = SSL3_MT_END_OF_EARLY_DATA;
- break;
-
- case TLS_ST_PENDING_EARLY_DATA_END:
- *confunc = NULL;
- *mt = SSL3_MT_DUMMY;
- break;
-
- case TLS_ST_CW_CERT:
- *confunc = tls_construct_client_certificate;
- *mt = SSL3_MT_CERTIFICATE;
- break;
-
- case TLS_ST_CW_KEY_EXCH:
- *confunc = tls_construct_client_key_exchange;
- *mt = SSL3_MT_CLIENT_KEY_EXCHANGE;
- break;
-
- case TLS_ST_CW_CERT_VRFY:
- *confunc = tls_construct_cert_verify;
- *mt = SSL3_MT_CERTIFICATE_VERIFY;
- break;
-
-#if !defined(OPENSSL_NO_NEXTPROTONEG)
- case TLS_ST_CW_NEXT_PROTO:
- *confunc = tls_construct_next_proto;
- *mt = SSL3_MT_NEXT_PROTO;
- break;
-#endif
- case TLS_ST_CW_FINISHED:
- *confunc = tls_construct_finished;
- *mt = SSL3_MT_FINISHED;
- break;
-
- case TLS_ST_CW_KEY_UPDATE:
- *confunc = tls_construct_key_update;
- *mt = SSL3_MT_KEY_UPDATE;
- break;
- }
-
- return 1;
-}
-
-/*
- * Returns the maximum allowed length for the current message that we are
- * reading. Excludes the message header.
- */
-size_t ossl_statem_client_max_message_size(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- return 0;
-
- case TLS_ST_CR_SRVR_HELLO:
- return SERVER_HELLO_MAX_LENGTH;
-
- case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
- return HELLO_VERIFY_REQUEST_MAX_LENGTH;
-
- case TLS_ST_CR_CERT:
- return s->max_cert_list;
-
- case TLS_ST_CR_CERT_VRFY:
- return SSL3_RT_MAX_PLAIN_LENGTH;
-
- case TLS_ST_CR_CERT_STATUS:
- return SSL3_RT_MAX_PLAIN_LENGTH;
-
- case TLS_ST_CR_KEY_EXCH:
- return SERVER_KEY_EXCH_MAX_LENGTH;
-
- case TLS_ST_CR_CERT_REQ:
- /*
- * Set to s->max_cert_list for compatibility with previous releases. In
- * practice these messages can get quite long if servers are configured
- * to provide a long list of acceptable CAs
- */
- return s->max_cert_list;
-
- case TLS_ST_CR_SRVR_DONE:
- return SERVER_HELLO_DONE_MAX_LENGTH;
-
- case TLS_ST_CR_CHANGE:
- if (s->version == DTLS1_BAD_VER)
- return 3;
- return CCS_MAX_LENGTH;
-
- case TLS_ST_CR_SESSION_TICKET:
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/engine.h>
+#include <internal/cryptlib.h>
+
+static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
+static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
+
+static ossl_inline int cert_req_allowed(SSL *s);
+static int key_exchange_expected(SSL *s);
+static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
+ WPACKET *pkt);
+
+/*
+ * Is a CertificateRequest message allowed at the moment or not?
+ *
+ * Return values are:
+ * 1: Yes
+ * 0: No
+ */
+static ossl_inline int cert_req_allowed(SSL *s)
+{
+ /* TLS does not like anon-DH with client cert */
+ if ((s->version > SSL3_VERSION
+ && (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
+ || (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK)))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Should we expect the ServerKeyExchange message or not?
+ *
+ * Return values are:
+ * 1: Yes
+ * 0: No
+ */
+static int key_exchange_expected(SSL *s)
+{
+ long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ /*
+ * Can't skip server key exchange if this is an ephemeral
+ * ciphersuite or for SRP
+ */
+ if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK
+ | SSL_kSRP)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * ossl_statem_client_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when a TLS1.3 client is reading messages from the
+ * server. The message type that the server has sent is provided in |mt|. The
+ * current state is in |s->statem.hand_state|.
+ *
+ * Return values are 1 for success (transition allowed) and 0 on error
+ * (transition not allowed)
+ */
+static int ossl_statem_client13_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note: There is no case for TLS_ST_CW_CLNT_HELLO, because we haven't
+ * yet negotiated TLSv1.3 at that point so that is handled by
+ * ossl_statem_client_read_transition()
+ */
+
+ switch (st->hand_state) {
+ default:
+ break;
+
+ case TLS_ST_CW_CLNT_HELLO:
+ /*
+ * This must a ClientHello following a HelloRetryRequest, so the only
+ * thing we can get now is a ServerHello.
+ */
+ if (mt == SSL3_MT_SERVER_HELLO) {
+ st->hand_state = TLS_ST_CR_SRVR_HELLO;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_SRVR_HELLO:
+ if (mt == SSL3_MT_ENCRYPTED_EXTENSIONS) {
+ st->hand_state = TLS_ST_CR_ENCRYPTED_EXTENSIONS;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
+ if (s->hit) {
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_CR_FINISHED;
+ return 1;
+ }
+ } else {
+ if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
+ st->hand_state = TLS_ST_CR_CERT_REQ;
+ return 1;
+ }
+ if (mt == SSL3_MT_CERTIFICATE) {
+ st->hand_state = TLS_ST_CR_CERT;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_CR_CERT_REQ:
+ if (mt == SSL3_MT_CERTIFICATE) {
+ st->hand_state = TLS_ST_CR_CERT;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_CERT:
+ if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
+ st->hand_state = TLS_ST_CR_CERT_VRFY;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_CERT_VRFY:
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_CR_FINISHED;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_OK:
+ if (mt == SSL3_MT_NEWSESSION_TICKET) {
+ st->hand_state = TLS_ST_CR_SESSION_TICKET;
+ return 1;
+ }
+ if (mt == SSL3_MT_KEY_UPDATE) {
+ st->hand_state = TLS_ST_CR_KEY_UPDATE;
+ return 1;
+ }
+ if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
+#if DTLS_MAX_VERSION != DTLS1_2_VERSION
+# error TODO(DTLS1.3): Restore digest for PHA before adding message.
+#endif
+ if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) {
+ s->post_handshake_auth = SSL_PHA_REQUESTED;
+ /*
+ * In TLS, this is called before the message is added to the
+ * digest. In DTLS, this is expected to be called after adding
+ * to the digest. Either move the digest restore, or add the
+ * message here after the swap, or do it after the clientFinished?
+ */
+ if (!tls13_restore_handshake_digest_for_pha(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ st->hand_state = TLS_ST_CR_CERT_REQ;
+ return 1;
+ }
+ }
+ break;
+ }
+
+ /* No valid transition found */
+ return 0;
+}
+
+/*
+ * ossl_statem_client_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when the client is reading messages from the
+ * server. The message type that the server has sent is provided in |mt|. The
+ * current state is in |s->statem.hand_state|.
+ *
+ * Return values are 1 for success (transition allowed) and 0 on error
+ * (transition not allowed)
+ */
+int ossl_statem_client_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+ int ske_expected;
+
+ /*
+ * Note that after writing the first ClientHello we don't know what version
+ * we are going to negotiate yet, so we don't take this branch until later.
+ */
+ if (SSL_IS_TLS13(s)) {
+ if (!ossl_statem_client13_read_transition(s, mt))
+ goto err;
+ return 1;
+ }
+
+ switch (st->hand_state) {
+ default:
+ break;
+
+ case TLS_ST_CW_CLNT_HELLO:
+ if (mt == SSL3_MT_SERVER_HELLO) {
+ st->hand_state = TLS_ST_CR_SRVR_HELLO;
+ return 1;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ if (mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_EARLY_DATA:
+ /*
+ * We've not actually selected TLSv1.3 yet, but we have sent early
+ * data. The only thing allowed now is a ServerHello or a
+ * HelloRetryRequest.
+ */
+ if (mt == SSL3_MT_SERVER_HELLO) {
+ st->hand_state = TLS_ST_CR_SRVR_HELLO;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_SRVR_HELLO:
+ if (s->hit) {
+ if (s->ext.ticket_expected) {
+ if (mt == SSL3_MT_NEWSESSION_TICKET) {
+ st->hand_state = TLS_ST_CR_SESSION_TICKET;
+ return 1;
+ }
+ } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_CR_CHANGE;
+ return 1;
+ }
+ } else {
+ if (SSL_IS_DTLS(s) && mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
+ return 1;
+ } else if (s->version >= TLS1_VERSION
+ && s->ext.session_secret_cb != NULL
+ && s->session->ext.tick != NULL
+ && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ /*
+ * Normally, we can tell if the server is resuming the session
+ * from the session ID. EAP-FAST (RFC 4851), however, relies on
+ * the next server message after the ServerHello to determine if
+ * the server is resuming.
+ */
+ s->hit = 1;
+ st->hand_state = TLS_ST_CR_CHANGE;
+ return 1;
+ } else if (!(s->s3->tmp.new_cipher->algorithm_auth
+ & (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
+ if (mt == SSL3_MT_CERTIFICATE) {
+ st->hand_state = TLS_ST_CR_CERT;
+ return 1;
+ }
+ } else {
+ ske_expected = key_exchange_expected(s);
+ /* SKE is optional for some PSK ciphersuites */
+ if (ske_expected
+ || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
+ && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
+ if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
+ st->hand_state = TLS_ST_CR_KEY_EXCH;
+ return 1;
+ }
+ } else if (mt == SSL3_MT_CERTIFICATE_REQUEST
+ && cert_req_allowed(s)) {
+ st->hand_state = TLS_ST_CR_CERT_REQ;
+ return 1;
+ } else if (mt == SSL3_MT_SERVER_DONE) {
+ st->hand_state = TLS_ST_CR_SRVR_DONE;
+ return 1;
+ }
+ }
+ }
+ break;
+
+ case TLS_ST_CR_CERT:
+ /*
+ * The CertificateStatus message is optional even if
+ * |ext.status_expected| is set
+ */
+ if (s->ext.status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) {
+ st->hand_state = TLS_ST_CR_CERT_STATUS;
+ return 1;
+ }
+ /* Fall through */
+
+ case TLS_ST_CR_CERT_STATUS:
+ ske_expected = key_exchange_expected(s);
+ /* SKE is optional for some PSK ciphersuites */
+ if (ske_expected || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
+ && mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
+ if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
+ st->hand_state = TLS_ST_CR_KEY_EXCH;
+ return 1;
+ }
+ goto err;
+ }
+ /* Fall through */
+
+ case TLS_ST_CR_KEY_EXCH:
+ if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
+ if (cert_req_allowed(s)) {
+ st->hand_state = TLS_ST_CR_CERT_REQ;
+ return 1;
+ }
+ goto err;
+ }
+ /* Fall through */
+
+ case TLS_ST_CR_CERT_REQ:
+ if (mt == SSL3_MT_SERVER_DONE) {
+ st->hand_state = TLS_ST_CR_SRVR_DONE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CW_FINISHED:
+ if (s->ext.ticket_expected) {
+ if (mt == SSL3_MT_NEWSESSION_TICKET) {
+ st->hand_state = TLS_ST_CR_SESSION_TICKET;
+ return 1;
+ }
+ } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_CR_CHANGE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_SESSION_TICKET:
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_CR_CHANGE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_CHANGE:
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_CR_FINISHED;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_OK:
+ if (mt == SSL3_MT_HELLO_REQUEST) {
+ st->hand_state = TLS_ST_CR_HELLO_REQ;
+ return 1;
+ }
+ break;
+ }
+
+ err:
+ /* No valid transition found */
+ if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ BIO *rbio;
+
+ /*
+ * CCS messages don't have a message sequence number so this is probably
+ * because of an out-of-order CCS. We'll just drop it.
+ */
+ s->init_num = 0;
+ s->rwstate = SSL_READING;
+ rbio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(rbio);
+ BIO_set_retry_read(rbio);
+ return 0;
+ }
+ SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
+ SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION,
+ SSL_R_UNEXPECTED_MESSAGE);
+ return 0;
+}
+
+/*
+ * ossl_statem_client13_write_transition() works out what handshake state to
+ * move to next when the TLSv1.3 client is writing messages to be sent to the
+ * server.
+ */
+static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
+ * TLSv1.3 yet at that point. They are handled by
+ * ossl_statem_client_write_transition().
+ */
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
+ ERR_R_INTERNAL_ERROR);
+ return WRITE_TRAN_ERROR;
+
+ case TLS_ST_CR_CERT_REQ:
+ if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
+ st->hand_state = TLS_ST_CW_CERT;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /*
+ * We should only get here if we received a CertificateRequest after
+ * we already sent close_notify
+ */
+ if (!ossl_assert((s->shutdown & SSL_SENT_SHUTDOWN) != 0)) {
+ /* Shouldn't happen - same as default case */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
+ ERR_R_INTERNAL_ERROR);
+ return WRITE_TRAN_ERROR;
+ }
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CR_FINISHED:
+ if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
+ || s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING)
+ st->hand_state = TLS_ST_PENDING_EARLY_DATA_END;
+ else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
+ && s->hello_retry_request == SSL_HRR_NONE)
+ st->hand_state = TLS_ST_CW_CHANGE;
+ else
+ st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
+ : TLS_ST_CW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_PENDING_EARLY_DATA_END:
+ if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
+ st->hand_state = TLS_ST_CW_END_OF_EARLY_DATA;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_CW_END_OF_EARLY_DATA:
+ case TLS_ST_CW_CHANGE:
+ st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
+ : TLS_ST_CW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CERT:
+ /* If a non-empty Certificate we also send CertificateVerify */
+ st->hand_state = (s->s3->tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY
+ : TLS_ST_CW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CERT_VRFY:
+ st->hand_state = TLS_ST_CW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CR_KEY_UPDATE:
+ case TLS_ST_CW_KEY_UPDATE:
+ case TLS_ST_CR_SESSION_TICKET:
+ case TLS_ST_CW_FINISHED:
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_OK:
+ if (s->key_update != SSL_KEY_UPDATE_NONE) {
+ st->hand_state = TLS_ST_CW_KEY_UPDATE;
+ return WRITE_TRAN_CONTINUE;
+ }
+
+ /* Try to read from the server instead */
+ return WRITE_TRAN_FINISHED;
+ }
+}
+
+/*
+ * ossl_statem_client_write_transition() works out what handshake state to
+ * move to next when the client is writing messages to be sent to the server.
+ */
+WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note that immediately before/after a ClientHello we don't know what
+ * version we are going to negotiate yet, so we don't take this branch until
+ * later
+ */
+ if (SSL_IS_TLS13(s))
+ return ossl_statem_client13_write_transition(s);
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION,
+ ERR_R_INTERNAL_ERROR);
+ return WRITE_TRAN_ERROR;
+
+ case TLS_ST_OK:
+ if (!s->renegotiate) {
+ /*
+ * We haven't requested a renegotiation ourselves so we must have
+ * received a message from the server. Better read it.
+ */
+ return WRITE_TRAN_FINISHED;
+ }
+ /* Renegotiation */
+ /* fall thru */
+ case TLS_ST_BEFORE:
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CLNT_HELLO:
+ if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
+ /*
+ * We are assuming this is a TLSv1.3 connection, although we haven't
+ * actually selected a version yet.
+ */
+ if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
+ st->hand_state = TLS_ST_CW_CHANGE;
+ else
+ st->hand_state = TLS_ST_EARLY_DATA;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /*
+ * No transition at the end of writing because we don't know what
+ * we will be sent
+ */
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_CR_SRVR_HELLO:
+ /*
+ * We only get here in TLSv1.3. We just received an HRR, so issue a
+ * CCS unless middlebox compat mode is off, or we already issued one
+ * because we did early data.
+ */
+ if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
+ && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
+ st->hand_state = TLS_ST_CW_CHANGE;
+ else
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_EARLY_DATA:
+ return WRITE_TRAN_FINISHED;
+
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CR_SRVR_DONE:
+ if (s->s3->tmp.cert_req)
+ st->hand_state = TLS_ST_CW_CERT;
+ else
+ st->hand_state = TLS_ST_CW_KEY_EXCH;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CERT:
+ st->hand_state = TLS_ST_CW_KEY_EXCH;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_KEY_EXCH:
+ /*
+ * For TLS, cert_req is set to 2, so a cert chain of nothing is
+ * sent, but no verify packet is sent
+ */
+ /*
+ * XXX: For now, we do not support client authentication in ECDH
+ * cipher suites with ECDH (rather than ECDSA) certificates. We
+ * need to skip the certificate verify message when client's
+ * ECDH public key is sent inside the client certificate.
+ */
+ if (s->s3->tmp.cert_req == 1) {
+ st->hand_state = TLS_ST_CW_CERT_VRFY;
+ } else {
+ st->hand_state = TLS_ST_CW_CHANGE;
+ }
+ if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) {
+ st->hand_state = TLS_ST_CW_CHANGE;
+ }
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CERT_VRFY:
+ st->hand_state = TLS_ST_CW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CHANGE:
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ } else if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
+ st->hand_state = TLS_ST_EARLY_DATA;
+ } else {
+#if defined(OPENSSL_NO_NEXTPROTONEG)
+ st->hand_state = TLS_ST_CW_FINISHED;
+#else
+ if (!SSL_IS_DTLS(s) && s->s3->npn_seen)
+ st->hand_state = TLS_ST_CW_NEXT_PROTO;
+ else
+ st->hand_state = TLS_ST_CW_FINISHED;
+#endif
+ }
+ return WRITE_TRAN_CONTINUE;
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ case TLS_ST_CW_NEXT_PROTO:
+ st->hand_state = TLS_ST_CW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+#endif
+
+ case TLS_ST_CW_FINISHED:
+ if (s->hit) {
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+ } else {
+ return WRITE_TRAN_FINISHED;
+ }
+
+ case TLS_ST_CR_FINISHED:
+ if (s->hit) {
+ st->hand_state = TLS_ST_CW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+ } else {
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+ }
+
+ case TLS_ST_CR_HELLO_REQ:
+ /*
+ * If we can renegotiate now then do so, otherwise wait for a more
+ * convenient time.
+ */
+ if (ssl3_renegotiate_check(s, 1)) {
+ if (!tls_setup_handshake(s)) {
+ /* SSLfatal() already called */
+ return WRITE_TRAN_ERROR;
+ }
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ return WRITE_TRAN_CONTINUE;
+ }
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+ }
+}
+
+/*
+ * Perform any pre work that needs to be done prior to sending a message from
+ * the client to the server.
+ */
+WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* No pre work to be done */
+ break;
+
+ case TLS_ST_CW_CLNT_HELLO:
+ s->shutdown = 0;
+ if (SSL_IS_DTLS(s)) {
+ /* every DTLS ClientHello resets Finished MAC */
+ if (!ssl3_init_finished_mac(s)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ }
+ break;
+
+ case TLS_ST_CW_CHANGE:
+ if (SSL_IS_DTLS(s)) {
+ if (s->hit) {
+ /*
+ * We're into the last flight so we don't retransmit these
+ * messages unless we need to.
+ */
+ st->use_timer = 0;
+ }
+#ifndef OPENSSL_NO_SCTP
+ if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ /* Calls SSLfatal() as required */
+ return dtls_wait_for_dry(s);
+ }
+#endif
+ }
+ break;
+
+ case TLS_ST_PENDING_EARLY_DATA_END:
+ /*
+ * If we've been called by SSL_do_handshake()/SSL_write(), or we did not
+ * attempt to write early data before calling SSL_read() then we press
+ * on with the handshake. Otherwise we pause here.
+ */
+ if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING
+ || s->early_data_state == SSL_EARLY_DATA_NONE)
+ return WORK_FINISHED_CONTINUE;
+ /* Fall through */
+
+ case TLS_ST_EARLY_DATA:
+ return tls_finish_handshake(s, wst, 0, 1);
+
+ case TLS_ST_OK:
+ /* Calls SSLfatal() as required */
+ return tls_finish_handshake(s, wst, 1, 1);
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+/*
+ * Perform any work that needs to be done after sending a message from the
+ * client to the server.
+ */
+WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ s->init_num = 0;
+
+ switch (st->hand_state) {
+ default:
+ /* No post work to be done */
+ break;
+
+ case TLS_ST_CW_CLNT_HELLO:
+ if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
+ && s->max_early_data > 0) {
+ /*
+ * We haven't selected TLSv1.3 yet so we don't call the change
+ * cipher state function associated with the SSL_METHOD. Instead
+ * we call tls13_change_cipher_state() directly.
+ */
+ if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) {
+ if (!tls13_change_cipher_state(s,
+ SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ }
+ /* else we're in compat mode so we delay flushing until after CCS */
+ } else if (!statem_flush(s)) {
+ return WORK_MORE_A;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ /* Treat the next message as the first packet */
+ s->first_packet = 1;
+ }
+ break;
+
+ case TLS_ST_CW_END_OF_EARLY_DATA:
+ /*
+ * We set the enc_write_ctx back to NULL because we may end up writing
+ * in cleartext again if we get a HelloRetryRequest from the server.
+ */
+ EVP_CIPHER_CTX_free(s->enc_write_ctx);
+ s->enc_write_ctx = NULL;
+ break;
+
+ case TLS_ST_CW_KEY_EXCH:
+ if (tls_client_key_exchange_post_work(s) == 0) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ break;
+
+ case TLS_ST_CW_CHANGE:
+ if (SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING)
+ break;
+ if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
+ && s->max_early_data > 0) {
+ /*
+ * We haven't selected TLSv1.3 yet so we don't call the change
+ * cipher state function associated with the SSL_METHOD. Instead
+ * we call tls13_change_cipher_state() directly.
+ */
+ if (!tls13_change_cipher_state(s,
+ SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+ return WORK_ERROR;
+ break;
+ }
+ s->session->cipher = s->s3->tmp.new_cipher;
+#ifdef OPENSSL_NO_COMP
+ s->session->compress_meth = 0;
+#else
+ if (s->s3->tmp.new_compression == NULL)
+ s->session->compress_meth = 0;
+ else
+ s->session->compress_meth = s->s3->tmp.new_compression->id;
+#endif
+ if (!s->method->ssl3_enc->setup_key_block(s)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+#ifndef OPENSSL_NO_SCTP
+ if (s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ }
+ break;
+
+ case TLS_ST_CW_FINISHED:
+#ifndef OPENSSL_NO_SCTP
+ if (wst == WORK_MORE_A && SSL_IS_DTLS(s) && s->hit == 0) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+ if (statem_flush(s) != 1)
+ return WORK_MORE_B;
+
+ if (SSL_IS_TLS13(s)) {
+ if (!tls13_save_handshake_digest_for_pha(s)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ if (s->post_handshake_auth != SSL_PHA_REQUESTED) {
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ }
+ }
+ break;
+
+ case TLS_ST_CW_KEY_UPDATE:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ if (!tls13_update_key(s, 1)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ break;
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+/*
+ * Get the message construction function and message type for sending from the
+ * client
+ *
+ * Valid return values are:
+ * 1: Success
+ * 0: Error
+ */
+int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
+ confunc_f *confunc, int *mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE,
+ SSL_R_BAD_HANDSHAKE_STATE);
+ return 0;
+
+ case TLS_ST_CW_CHANGE:
+ if (SSL_IS_DTLS(s))
+ *confunc = dtls_construct_change_cipher_spec;
+ else
+ *confunc = tls_construct_change_cipher_spec;
+ *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
+ break;
+
+ case TLS_ST_CW_CLNT_HELLO:
+ *confunc = tls_construct_client_hello;
+ *mt = SSL3_MT_CLIENT_HELLO;
+ break;
+
+ case TLS_ST_CW_END_OF_EARLY_DATA:
+ *confunc = tls_construct_end_of_early_data;
+ *mt = SSL3_MT_END_OF_EARLY_DATA;
+ break;
+
+ case TLS_ST_PENDING_EARLY_DATA_END:
+ *confunc = NULL;
+ *mt = SSL3_MT_DUMMY;
+ break;
+
+ case TLS_ST_CW_CERT:
+ *confunc = tls_construct_client_certificate;
+ *mt = SSL3_MT_CERTIFICATE;
+ break;
+
+ case TLS_ST_CW_KEY_EXCH:
+ *confunc = tls_construct_client_key_exchange;
+ *mt = SSL3_MT_CLIENT_KEY_EXCHANGE;
+ break;
+
+ case TLS_ST_CW_CERT_VRFY:
+ *confunc = tls_construct_cert_verify;
+ *mt = SSL3_MT_CERTIFICATE_VERIFY;
+ break;
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+ case TLS_ST_CW_NEXT_PROTO:
+ *confunc = tls_construct_next_proto;
+ *mt = SSL3_MT_NEXT_PROTO;
+ break;
+#endif
+ case TLS_ST_CW_FINISHED:
+ *confunc = tls_construct_finished;
+ *mt = SSL3_MT_FINISHED;
+ break;
+
+ case TLS_ST_CW_KEY_UPDATE:
+ *confunc = tls_construct_key_update;
+ *mt = SSL3_MT_KEY_UPDATE;
+ break;
+ }
+
+ return 1;
+}
+
+/*
+ * Returns the maximum allowed length for the current message that we are
+ * reading. Excludes the message header.
+ */
+size_t ossl_statem_client_max_message_size(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ return 0;
+
+ case TLS_ST_CR_SRVR_HELLO:
+ return SERVER_HELLO_MAX_LENGTH;
+
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ return HELLO_VERIFY_REQUEST_MAX_LENGTH;
+
+ case TLS_ST_CR_CERT:
+ return s->max_cert_list;
+
+ case TLS_ST_CR_CERT_VRFY:
+ return SSL3_RT_MAX_PLAIN_LENGTH;
+
+ case TLS_ST_CR_CERT_STATUS:
+ return SSL3_RT_MAX_PLAIN_LENGTH;
+
+ case TLS_ST_CR_KEY_EXCH:
+ return SERVER_KEY_EXCH_MAX_LENGTH;
+
+ case TLS_ST_CR_CERT_REQ:
+ /*
+ * Set to s->max_cert_list for compatibility with previous releases. In
+ * practice these messages can get quite long if servers are configured
+ * to provide a long list of acceptable CAs
+ */
+ return s->max_cert_list;
+
+ case TLS_ST_CR_SRVR_DONE:
+ return SERVER_HELLO_DONE_MAX_LENGTH;
+
+ case TLS_ST_CR_CHANGE:
+ if (s->version == DTLS1_BAD_VER)
+ return 3;
+ return CCS_MAX_LENGTH;
+
+ case TLS_ST_CR_SESSION_TICKET:
return (SSL_IS_TLS13(s)) ? SESSION_TICKET_MAX_LENGTH_TLS13
: SESSION_TICKET_MAX_LENGTH_TLS12;
-
- case TLS_ST_CR_FINISHED:
- return FINISHED_MAX_LENGTH;
-
- case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
- return ENCRYPTED_EXTENSIONS_MAX_LENGTH;
-
- case TLS_ST_CR_KEY_UPDATE:
- return KEY_UPDATE_MAX_LENGTH;
- }
-}
-
-/*
- * Process a message that the client has been received from the server.
- */
-MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
- return MSG_PROCESS_ERROR;
-
- case TLS_ST_CR_SRVR_HELLO:
- return tls_process_server_hello(s, pkt);
-
- case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
- return dtls_process_hello_verify(s, pkt);
-
- case TLS_ST_CR_CERT:
- return tls_process_server_certificate(s, pkt);
-
- case TLS_ST_CR_CERT_VRFY:
- return tls_process_cert_verify(s, pkt);
-
- case TLS_ST_CR_CERT_STATUS:
- return tls_process_cert_status(s, pkt);
-
- case TLS_ST_CR_KEY_EXCH:
- return tls_process_key_exchange(s, pkt);
-
- case TLS_ST_CR_CERT_REQ:
- return tls_process_certificate_request(s, pkt);
-
- case TLS_ST_CR_SRVR_DONE:
- return tls_process_server_done(s, pkt);
-
- case TLS_ST_CR_CHANGE:
- return tls_process_change_cipher_spec(s, pkt);
-
- case TLS_ST_CR_SESSION_TICKET:
- return tls_process_new_session_ticket(s, pkt);
-
- case TLS_ST_CR_FINISHED:
- return tls_process_finished(s, pkt);
-
- case TLS_ST_CR_HELLO_REQ:
- return tls_process_hello_req(s, pkt);
-
- case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
- return tls_process_encrypted_extensions(s, pkt);
-
- case TLS_ST_CR_KEY_UPDATE:
- return tls_process_key_update(s, pkt);
- }
-}
-
-/*
- * Perform any further processing required following the receipt of a message
- * from the server
- */
-WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
-
- case TLS_ST_CR_CERT_VRFY:
- case TLS_ST_CR_CERT_REQ:
- return tls_prepare_client_certificate(s, wst);
- }
-}
-
-int tls_construct_client_hello(SSL *s, WPACKET *pkt)
-{
- unsigned char *p;
- size_t sess_id_len;
- int i, protverr;
-#ifndef OPENSSL_NO_COMP
- SSL_COMP *comp;
-#endif
- SSL_SESSION *sess = s->session;
- unsigned char *session_id;
-
- /* Work out what SSL/TLS/DTLS version to use */
- protverr = ssl_set_client_hello_version(s);
- if (protverr != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- protverr);
- return 0;
- }
-
- if (sess == NULL
- || !ssl_version_supported(s, sess->ssl_version, NULL)
- || !SSL_SESSION_is_resumable(sess)) {
- if (s->hello_retry_request == SSL_HRR_NONE
- && !ssl_get_new_session(s, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
- /* else use the pre-loaded session */
-
- p = s->s3->client_random;
-
- /*
- * for DTLS if client_random is initialized, reuse it, we are
- * required to use same upon reply to HelloVerify
- */
- if (SSL_IS_DTLS(s)) {
- size_t idx;
- i = 1;
- for (idx = 0; idx < sizeof(s->s3->client_random); idx++) {
- if (p[idx]) {
- i = 0;
- break;
- }
- }
- } else {
- i = (s->hello_retry_request == SSL_HRR_NONE);
- }
-
- if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random),
- DOWNGRADE_NONE) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*-
- * version indicates the negotiated version: for example from
- * an SSLv2/v3 compatible client hello). The client_version
- * field is the maximum version we permit and it is also
- * used in RSA encrypted premaster secrets. Some servers can
- * choke if we initially report a higher version then
- * renegotiate to a lower one in the premaster secret. This
- * didn't happen with TLS 1.0 as most servers supported it
- * but it can with TLS 1.1 or later if the server only supports
- * 1.0.
- *
- * Possible scenario with previous logic:
- * 1. Client hello indicates TLS 1.2
- * 2. Server hello says TLS 1.0
- * 3. RSA encrypted premaster secret uses 1.2.
- * 4. Handshake proceeds using TLS 1.0.
- * 5. Server sends hello request to renegotiate.
- * 6. Client hello indicates TLS v1.0 as we now
- * know that is maximum server supports.
- * 7. Server chokes on RSA encrypted premaster secret
- * containing version 1.0.
- *
- * For interoperability it should be OK to always use the
- * maximum version we support in client hello and then rely
- * on the checking of version to ensure the servers isn't
- * being inconsistent: for example initially negotiating with
- * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
- * client_version in client hello and not resetting it to
- * the negotiated version.
- *
- * For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the
- * supported_versions extension for the real supported versions.
- */
- if (!WPACKET_put_bytes_u16(pkt, s->client_version)
- || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* Session ID */
- session_id = s->session->session_id;
- if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) {
- if (s->version == TLS1_3_VERSION
- && (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) {
- sess_id_len = sizeof(s->tmp_session_id);
- s->tmp_session_id_len = sess_id_len;
- session_id = s->tmp_session_id;
- if (s->hello_retry_request == SSL_HRR_NONE
- && RAND_bytes(s->tmp_session_id, sess_id_len) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- } else {
- sess_id_len = 0;
- }
- } else {
- assert(s->session->session_id_length <= sizeof(s->session->session_id));
- sess_id_len = s->session->session_id_length;
- if (s->version == TLS1_3_VERSION) {
- s->tmp_session_id_len = sess_id_len;
- memcpy(s->tmp_session_id, s->session->session_id, sess_id_len);
- }
- }
- if (!WPACKET_start_sub_packet_u8(pkt)
- || (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id,
- sess_id_len))
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* cookie stuff for DTLS */
- if (SSL_IS_DTLS(s)) {
- if (s->d1->cookie_len > sizeof(s->d1->cookie)
- || !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
- s->d1->cookie_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- /* Ciphers supported */
- if (!WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) {
- /* SSLfatal() already called */
- return 0;
- }
- if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* COMPRESSION */
- if (!WPACKET_start_sub_packet_u8(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-#ifndef OPENSSL_NO_COMP
- if (ssl_allow_compression(s)
- && s->ctx->comp_methods
- && (SSL_IS_DTLS(s) || s->s3->tmp.max_ver < TLS1_3_VERSION)) {
- int compnum = sk_SSL_COMP_num(s->ctx->comp_methods);
- for (i = 0; i < compnum; i++) {
- comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
- if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- }
-#endif
- /* Add the NULL method */
- if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* TLS extensions */
- if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
-{
- size_t cookie_len;
- PACKET cookiepkt;
-
- if (!PACKET_forward(pkt, 2)
- || !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- cookie_len = PACKET_remaining(&cookiepkt);
- if (cookie_len > sizeof(s->d1->cookie)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
- SSL_R_LENGTH_TOO_LONG);
- return MSG_PROCESS_ERROR;
- }
-
- if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
- s->d1->cookie_len = cookie_len;
-
- return MSG_PROCESS_FINISHED_READING;
-}
-
-static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
-{
- STACK_OF(SSL_CIPHER) *sk;
- const SSL_CIPHER *c;
- int i;
-
- c = ssl_get_cipher_by_char(s, cipherchars, 0);
- if (c == NULL) {
- /* unknown cipher */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_UNKNOWN_CIPHER_RETURNED);
- return 0;
- }
- /*
- * If it is a disabled cipher we either didn't send it in client hello,
- * or it's not allowed for the selected protocol. So we return an error.
- */
- if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_WRONG_CIPHER_RETURNED);
- return 0;
- }
-
- sk = ssl_get_ciphers_by_id(s);
- i = sk_SSL_CIPHER_find(sk, c);
- if (i < 0) {
- /* we did not say we would use this cipher */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_WRONG_CIPHER_RETURNED);
- return 0;
- }
-
- if (SSL_IS_TLS13(s) && s->s3->tmp.new_cipher != NULL
- && s->s3->tmp.new_cipher->id != c->id) {
- /* ServerHello selected a different ciphersuite to that in the HRR */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_WRONG_CIPHER_RETURNED);
- return 0;
- }
-
- /*
- * Depending on the session caching (internal/external), the cipher
- * and/or cipher_id values may not be set. Make sure that cipher_id is
- * set and use it for comparison.
- */
- if (s->session->cipher != NULL)
- s->session->cipher_id = s->session->cipher->id;
- if (s->hit && (s->session->cipher_id != c->id)) {
- if (SSL_IS_TLS13(s)) {
- /*
- * In TLSv1.3 it is valid for the server to select a different
- * ciphersuite as long as the hash is the same.
- */
- if (ssl_md(c->algorithm2)
- != ssl_md(s->session->cipher->algorithm2)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED);
- return 0;
- }
- } else {
- /*
- * Prior to TLSv1.3 resuming a session always meant using the same
- * ciphersuite.
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
- SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
- return 0;
- }
- }
- s->s3->tmp.new_cipher = c;
-
- return 1;
-}
-
-MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
-{
- PACKET session_id, extpkt;
- size_t session_id_len;
- const unsigned char *cipherchars;
- int hrr = 0;
- unsigned int compression;
- unsigned int sversion;
- unsigned int context;
- RAW_EXTENSION *extensions = NULL;
-#ifndef OPENSSL_NO_COMP
- SSL_COMP *comp;
-#endif
-
- if (!PACKET_get_net_2(pkt, &sversion)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- /* load the server random */
- if (s->version == TLS1_3_VERSION
- && sversion == TLS1_2_VERSION
- && PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE
- && memcmp(hrrrandom, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) {
- s->hello_retry_request = SSL_HRR_PENDING;
- hrr = 1;
- if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- } else {
- if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- }
-
- /* Get the session-id. */
- if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- session_id_len = PACKET_remaining(&session_id);
- if (session_id_len > sizeof(s->session->session_id)
- || session_id_len > SSL3_SESSION_ID_SIZE) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_SSL3_SESSION_ID_TOO_LONG);
- goto err;
- }
-
- if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!PACKET_get_1(pkt, &compression)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- /* TLS extensions */
- if (PACKET_remaining(pkt) == 0 && !hrr) {
- PACKET_null_init(&extpkt);
- } else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_BAD_LENGTH);
- goto err;
- }
-
- if (!hrr) {
- if (!tls_collect_extensions(s, &extpkt,
- SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_SERVER_HELLO,
- &extensions, NULL, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- if (!ssl_choose_client_version(s, sversion, extensions)) {
- /* SSLfatal() already called */
- goto err;
- }
- }
-
- if (SSL_IS_TLS13(s) || hrr) {
- if (compression != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_INVALID_COMPRESSION_ALGORITHM);
- goto err;
- }
-
- if (session_id_len != s->tmp_session_id_len
- || memcmp(PACKET_data(&session_id), s->tmp_session_id,
- session_id_len) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
- goto err;
- }
- }
-
- if (hrr) {
- if (!set_client_ciphersuite(s, cipherchars)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- return tls_process_as_hello_retry_request(s, &extpkt);
- }
-
- /*
- * Now we have chosen the version we need to check again that the extensions
- * are appropriate for this version.
- */
- context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
- : SSL_EXT_TLS1_2_SERVER_HELLO;
- if (!tls_validate_all_contexts(s, context, extensions)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_BAD_EXTENSION);
- goto err;
- }
-
- s->hit = 0;
-
- if (SSL_IS_TLS13(s)) {
- /*
- * In TLSv1.3 a ServerHello message signals a key change so the end of
- * the message must be on a record boundary.
- */
- if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
- goto err;
- }
-
- /* This will set s->hit if we are resuming */
- if (!tls_parse_extension(s, TLSEXT_IDX_psk,
- SSL_EXT_TLS1_3_SERVER_HELLO,
- extensions, NULL, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else {
- /*
- * Check if we can resume the session based on external pre-shared
- * secret. EAP-FAST (RFC 4851) supports two types of session resumption.
- * Resumption based on server-side state works with session IDs.
- * Resumption based on pre-shared Protected Access Credentials (PACs)
- * works by overriding the SessionTicket extension at the application
- * layer, and does not send a session ID. (We do not know whether
- * EAP-FAST servers would honour the session ID.) Therefore, the session
- * ID alone is not a reliable indicator of session resumption, so we
- * first check if we can resume, and later peek at the next handshake
- * message to see if the server wants to resume.
- */
- if (s->version >= TLS1_VERSION
- && s->ext.session_secret_cb != NULL && s->session->ext.tick) {
- const SSL_CIPHER *pref_cipher = NULL;
- /*
- * s->session->master_key_length is a size_t, but this is an int for
- * backwards compat reasons
- */
- int master_key_length;
- master_key_length = sizeof(s->session->master_key);
- if (s->ext.session_secret_cb(s, s->session->master_key,
- &master_key_length,
- NULL, &pref_cipher,
- s->ext.session_secret_cb_arg)
- && master_key_length > 0) {
- s->session->master_key_length = master_key_length;
- s->session->cipher = pref_cipher ?
- pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0);
- } else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
- if (session_id_len != 0
- && session_id_len == s->session->session_id_length
- && memcmp(PACKET_data(&session_id), s->session->session_id,
- session_id_len) == 0)
- s->hit = 1;
- }
-
- if (s->hit) {
- if (s->sid_ctx_length != s->session->sid_ctx_length
- || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
- /* actually a client application bug */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
- goto err;
- }
- } else {
- /*
- * If we were trying for session-id reuse but the server
- * didn't resume, make a new SSL_SESSION.
- * In the case of EAP-FAST and PAC, we do not send a session ID,
- * so the PAC-based session secret is always preserved. It'll be
- * overwritten if the server refuses resumption.
- */
+
+ case TLS_ST_CR_FINISHED:
+ return FINISHED_MAX_LENGTH;
+
+ case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
+ return ENCRYPTED_EXTENSIONS_MAX_LENGTH;
+
+ case TLS_ST_CR_KEY_UPDATE:
+ return KEY_UPDATE_MAX_LENGTH;
+ }
+}
+
+/*
+ * Process a message that the client has been received from the server.
+ */
+MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE,
+ ERR_R_INTERNAL_ERROR);
+ return MSG_PROCESS_ERROR;
+
+ case TLS_ST_CR_SRVR_HELLO:
+ return tls_process_server_hello(s, pkt);
+
+ case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
+ return dtls_process_hello_verify(s, pkt);
+
+ case TLS_ST_CR_CERT:
+ return tls_process_server_certificate(s, pkt);
+
+ case TLS_ST_CR_CERT_VRFY:
+ return tls_process_cert_verify(s, pkt);
+
+ case TLS_ST_CR_CERT_STATUS:
+ return tls_process_cert_status(s, pkt);
+
+ case TLS_ST_CR_KEY_EXCH:
+ return tls_process_key_exchange(s, pkt);
+
+ case TLS_ST_CR_CERT_REQ:
+ return tls_process_certificate_request(s, pkt);
+
+ case TLS_ST_CR_SRVR_DONE:
+ return tls_process_server_done(s, pkt);
+
+ case TLS_ST_CR_CHANGE:
+ return tls_process_change_cipher_spec(s, pkt);
+
+ case TLS_ST_CR_SESSION_TICKET:
+ return tls_process_new_session_ticket(s, pkt);
+
+ case TLS_ST_CR_FINISHED:
+ return tls_process_finished(s, pkt);
+
+ case TLS_ST_CR_HELLO_REQ:
+ return tls_process_hello_req(s, pkt);
+
+ case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
+ return tls_process_encrypted_extensions(s, pkt);
+
+ case TLS_ST_CR_KEY_UPDATE:
+ return tls_process_key_update(s, pkt);
+ }
+}
+
+/*
+ * Perform any further processing required following the receipt of a message
+ * from the server
+ */
+WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+
+ case TLS_ST_CR_CERT_VRFY:
+ case TLS_ST_CR_CERT_REQ:
+ return tls_prepare_client_certificate(s, wst);
+ }
+}
+
+int tls_construct_client_hello(SSL *s, WPACKET *pkt)
+{
+ unsigned char *p;
+ size_t sess_id_len;
+ int i, protverr;
+#ifndef OPENSSL_NO_COMP
+ SSL_COMP *comp;
+#endif
+ SSL_SESSION *sess = s->session;
+ unsigned char *session_id;
+
+ /* Work out what SSL/TLS/DTLS version to use */
+ protverr = ssl_set_client_hello_version(s);
+ if (protverr != 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ protverr);
+ return 0;
+ }
+
+ if (sess == NULL
+ || !ssl_version_supported(s, sess->ssl_version, NULL)
+ || !SSL_SESSION_is_resumable(sess)) {
+ if (s->hello_retry_request == SSL_HRR_NONE
+ && !ssl_get_new_session(s, 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+ /* else use the pre-loaded session */
+
+ p = s->s3->client_random;
+
+ /*
+ * for DTLS if client_random is initialized, reuse it, we are
+ * required to use same upon reply to HelloVerify
+ */
+ if (SSL_IS_DTLS(s)) {
+ size_t idx;
+ i = 1;
+ for (idx = 0; idx < sizeof(s->s3->client_random); idx++) {
+ if (p[idx]) {
+ i = 0;
+ break;
+ }
+ }
+ } else {
+ i = (s->hello_retry_request == SSL_HRR_NONE);
+ }
+
+ if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random),
+ DOWNGRADE_NONE) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*-
+ * version indicates the negotiated version: for example from
+ * an SSLv2/v3 compatible client hello). The client_version
+ * field is the maximum version we permit and it is also
+ * used in RSA encrypted premaster secrets. Some servers can
+ * choke if we initially report a higher version then
+ * renegotiate to a lower one in the premaster secret. This
+ * didn't happen with TLS 1.0 as most servers supported it
+ * but it can with TLS 1.1 or later if the server only supports
+ * 1.0.
+ *
+ * Possible scenario with previous logic:
+ * 1. Client hello indicates TLS 1.2
+ * 2. Server hello says TLS 1.0
+ * 3. RSA encrypted premaster secret uses 1.2.
+ * 4. Handshake proceeds using TLS 1.0.
+ * 5. Server sends hello request to renegotiate.
+ * 6. Client hello indicates TLS v1.0 as we now
+ * know that is maximum server supports.
+ * 7. Server chokes on RSA encrypted premaster secret
+ * containing version 1.0.
+ *
+ * For interoperability it should be OK to always use the
+ * maximum version we support in client hello and then rely
+ * on the checking of version to ensure the servers isn't
+ * being inconsistent: for example initially negotiating with
+ * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
+ * client_version in client hello and not resetting it to
+ * the negotiated version.
+ *
+ * For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the
+ * supported_versions extension for the real supported versions.
+ */
+ if (!WPACKET_put_bytes_u16(pkt, s->client_version)
+ || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Session ID */
+ session_id = s->session->session_id;
+ if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) {
+ if (s->version == TLS1_3_VERSION
+ && (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) {
+ sess_id_len = sizeof(s->tmp_session_id);
+ s->tmp_session_id_len = sess_id_len;
+ session_id = s->tmp_session_id;
+ if (s->hello_retry_request == SSL_HRR_NONE
+ && RAND_bytes(s->tmp_session_id, sess_id_len) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else {
+ sess_id_len = 0;
+ }
+ } else {
+ assert(s->session->session_id_length <= sizeof(s->session->session_id));
+ sess_id_len = s->session->session_id_length;
+ if (s->version == TLS1_3_VERSION) {
+ s->tmp_session_id_len = sess_id_len;
+ memcpy(s->tmp_session_id, s->session->session_id, sess_id_len);
+ }
+ }
+ if (!WPACKET_start_sub_packet_u8(pkt)
+ || (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id,
+ sess_id_len))
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* cookie stuff for DTLS */
+ if (SSL_IS_DTLS(s)) {
+ if (s->d1->cookie_len > sizeof(s->d1->cookie)
+ || !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
+ s->d1->cookie_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ /* Ciphers supported */
+ if (!WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ if (!WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* COMPRESSION */
+ if (!WPACKET_start_sub_packet_u8(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#ifndef OPENSSL_NO_COMP
+ if (ssl_allow_compression(s)
+ && s->ctx->comp_methods
+ && (SSL_IS_DTLS(s) || s->s3->tmp.max_ver < TLS1_3_VERSION)) {
+ int compnum = sk_SSL_COMP_num(s->ctx->comp_methods);
+ for (i = 0; i < compnum; i++) {
+ comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
+ if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ }
+#endif
+ /* Add the NULL method */
+ if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* TLS extensions */
+ if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
+{
+ size_t cookie_len;
+ PACKET cookiepkt;
+
+ if (!PACKET_forward(pkt, 2)
+ || !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ cookie_len = PACKET_remaining(&cookiepkt);
+ if (cookie_len > sizeof(s->d1->cookie)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
+ SSL_R_LENGTH_TOO_LONG);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+ s->d1->cookie_len = cookie_len;
+
+ return MSG_PROCESS_FINISHED_READING;
+}
+
+static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
+{
+ STACK_OF(SSL_CIPHER) *sk;
+ const SSL_CIPHER *c;
+ int i;
+
+ c = ssl_get_cipher_by_char(s, cipherchars, 0);
+ if (c == NULL) {
+ /* unknown cipher */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+ SSL_R_UNKNOWN_CIPHER_RETURNED);
+ return 0;
+ }
+ /*
+ * If it is a disabled cipher we either didn't send it in client hello,
+ * or it's not allowed for the selected protocol. So we return an error.
+ */
+ if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+ SSL_R_WRONG_CIPHER_RETURNED);
+ return 0;
+ }
+
+ sk = ssl_get_ciphers_by_id(s);
+ i = sk_SSL_CIPHER_find(sk, c);
+ if (i < 0) {
+ /* we did not say we would use this cipher */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+ SSL_R_WRONG_CIPHER_RETURNED);
+ return 0;
+ }
+
+ if (SSL_IS_TLS13(s) && s->s3->tmp.new_cipher != NULL
+ && s->s3->tmp.new_cipher->id != c->id) {
+ /* ServerHello selected a different ciphersuite to that in the HRR */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+ SSL_R_WRONG_CIPHER_RETURNED);
+ return 0;
+ }
+
+ /*
+ * Depending on the session caching (internal/external), the cipher
+ * and/or cipher_id values may not be set. Make sure that cipher_id is
+ * set and use it for comparison.
+ */
+ if (s->session->cipher != NULL)
+ s->session->cipher_id = s->session->cipher->id;
+ if (s->hit && (s->session->cipher_id != c->id)) {
+ if (SSL_IS_TLS13(s)) {
+ /*
+ * In TLSv1.3 it is valid for the server to select a different
+ * ciphersuite as long as the hash is the same.
+ */
+ if (ssl_md(c->algorithm2)
+ != ssl_md(s->session->cipher->algorithm2)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_SET_CLIENT_CIPHERSUITE,
+ SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED);
+ return 0;
+ }
+ } else {
+ /*
+ * Prior to TLSv1.3 resuming a session always meant using the same
+ * ciphersuite.
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+ SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+ return 0;
+ }
+ }
+ s->s3->tmp.new_cipher = c;
+
+ return 1;
+}
+
+MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
+{
+ PACKET session_id, extpkt;
+ size_t session_id_len;
+ const unsigned char *cipherchars;
+ int hrr = 0;
+ unsigned int compression;
+ unsigned int sversion;
+ unsigned int context;
+ RAW_EXTENSION *extensions = NULL;
+#ifndef OPENSSL_NO_COMP
+ SSL_COMP *comp;
+#endif
+
+ if (!PACKET_get_net_2(pkt, &sversion)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /* load the server random */
+ if (s->version == TLS1_3_VERSION
+ && sversion == TLS1_2_VERSION
+ && PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE
+ && memcmp(hrrrandom, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) {
+ s->hello_retry_request = SSL_HRR_PENDING;
+ hrr = 1;
+ if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ } else {
+ if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ }
+
+ /* Get the session-id. */
+ if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ session_id_len = PACKET_remaining(&session_id);
+ if (session_id_len > sizeof(s->session->session_id)
+ || session_id_len > SSL3_SESSION_ID_SIZE) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_SSL3_SESSION_ID_TOO_LONG);
+ goto err;
+ }
+
+ if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!PACKET_get_1(pkt, &compression)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /* TLS extensions */
+ if (PACKET_remaining(pkt) == 0 && !hrr) {
+ PACKET_null_init(&extpkt);
+ } else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_BAD_LENGTH);
+ goto err;
+ }
+
+ if (!hrr) {
+ if (!tls_collect_extensions(s, &extpkt,
+ SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_SERVER_HELLO,
+ &extensions, NULL, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ if (!ssl_choose_client_version(s, sversion, extensions)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+
+ if (SSL_IS_TLS13(s) || hrr) {
+ if (compression != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_INVALID_COMPRESSION_ALGORITHM);
+ goto err;
+ }
+
+ if (session_id_len != s->tmp_session_id_len
+ || memcmp(PACKET_data(&session_id), s->tmp_session_id,
+ session_id_len) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
+ goto err;
+ }
+ }
+
+ if (hrr) {
+ if (!set_client_ciphersuite(s, cipherchars)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ return tls_process_as_hello_retry_request(s, &extpkt);
+ }
+
+ /*
+ * Now we have chosen the version we need to check again that the extensions
+ * are appropriate for this version.
+ */
+ context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
+ : SSL_EXT_TLS1_2_SERVER_HELLO;
+ if (!tls_validate_all_contexts(s, context, extensions)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_BAD_EXTENSION);
+ goto err;
+ }
+
+ s->hit = 0;
+
+ if (SSL_IS_TLS13(s)) {
+ /*
+ * In TLSv1.3 a ServerHello message signals a key change so the end of
+ * the message must be on a record boundary.
+ */
+ if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_NOT_ON_RECORD_BOUNDARY);
+ goto err;
+ }
+
+ /* This will set s->hit if we are resuming */
+ if (!tls_parse_extension(s, TLSEXT_IDX_psk,
+ SSL_EXT_TLS1_3_SERVER_HELLO,
+ extensions, NULL, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else {
+ /*
+ * Check if we can resume the session based on external pre-shared
+ * secret. EAP-FAST (RFC 4851) supports two types of session resumption.
+ * Resumption based on server-side state works with session IDs.
+ * Resumption based on pre-shared Protected Access Credentials (PACs)
+ * works by overriding the SessionTicket extension at the application
+ * layer, and does not send a session ID. (We do not know whether
+ * EAP-FAST servers would honour the session ID.) Therefore, the session
+ * ID alone is not a reliable indicator of session resumption, so we
+ * first check if we can resume, and later peek at the next handshake
+ * message to see if the server wants to resume.
+ */
+ if (s->version >= TLS1_VERSION
+ && s->ext.session_secret_cb != NULL && s->session->ext.tick) {
+ const SSL_CIPHER *pref_cipher = NULL;
+ /*
+ * s->session->master_key_length is a size_t, but this is an int for
+ * backwards compat reasons
+ */
+ int master_key_length;
+ master_key_length = sizeof(s->session->master_key);
+ if (s->ext.session_secret_cb(s, s->session->master_key,
+ &master_key_length,
+ NULL, &pref_cipher,
+ s->ext.session_secret_cb_arg)
+ && master_key_length > 0) {
+ s->session->master_key_length = master_key_length;
+ s->session->cipher = pref_cipher ?
+ pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0);
+ } else {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (session_id_len != 0
+ && session_id_len == s->session->session_id_length
+ && memcmp(PACKET_data(&session_id), s->session->session_id,
+ session_id_len) == 0)
+ s->hit = 1;
+ }
+
+ if (s->hit) {
+ if (s->sid_ctx_length != s->session->sid_ctx_length
+ || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
+ /* actually a client application bug */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+ goto err;
+ }
+ } else {
+ /*
+ * If we were trying for session-id reuse but the server
+ * didn't resume, make a new SSL_SESSION.
+ * In the case of EAP-FAST and PAC, we do not send a session ID,
+ * so the PAC-based session secret is always preserved. It'll be
+ * overwritten if the server refuses resumption.
+ */
if (s->session->session_id_length > 0) {
- tsan_counter(&s->session_ctx->stats.sess_miss);
- if (!ssl_get_new_session(s, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
- }
-
- s->session->ssl_version = s->version;
- /*
- * In TLSv1.2 and below we save the session id we were sent so we can
- * resume it later. In TLSv1.3 the session id we were sent is just an
- * echo of what we originally sent in the ClientHello and should not be
- * used for resumption.
- */
- if (!SSL_IS_TLS13(s)) {
- s->session->session_id_length = session_id_len;
- /* session_id_len could be 0 */
- if (session_id_len > 0)
- memcpy(s->session->session_id, PACKET_data(&session_id),
- session_id_len);
- }
- }
-
- /* Session version and negotiated protocol version should match */
- if (s->version != s->session->ssl_version) {
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_SSL_SESSION_VERSION_MISMATCH);
- goto err;
- }
- /*
- * Now that we know the version, update the check to see if it's an allowed
- * version.
- */
- s->s3->tmp.min_ver = s->version;
- s->s3->tmp.max_ver = s->version;
-
- if (!set_client_ciphersuite(s, cipherchars)) {
- /* SSLfatal() already called */
- goto err;
- }
-
-#ifdef OPENSSL_NO_COMP
- if (compression != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
- goto err;
- }
- /*
- * If compression is disabled we'd better not try to resume a session
- * using compression.
- */
- if (s->session->compress_meth != 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_INCONSISTENT_COMPRESSION);
- goto err;
- }
-#else
- if (s->hit && compression != s->session->compress_meth) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
- goto err;
- }
- if (compression == 0)
- comp = NULL;
- else if (!ssl_allow_compression(s)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_COMPRESSION_DISABLED);
- goto err;
- } else {
- comp = ssl3_comp_find(s->ctx->comp_methods, compression);
- }
-
- if (compression != 0 && comp == NULL) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
- goto err;
- } else {
- s->s3->tmp.new_compression = comp;
- }
-#endif
-
- if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s) && s->hit) {
- unsigned char sctpauthkey[64];
- char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
- size_t labellen;
-
- /*
- * Add new shared key for SCTP-Auth, will be ignored if
- * no SCTP used.
- */
- memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
- sizeof(DTLS1_SCTP_AUTH_LABEL));
-
- /* Don't include the terminating zero. */
- labellen = sizeof(labelbuffer) - 1;
- if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
- labellen += 1;
-
- if (SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey),
- labelbuffer,
- labellen, NULL, 0, 0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- BIO_ctrl(SSL_get_wbio(s),
- BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
- sizeof(sctpauthkey), sctpauthkey);
- }
-#endif
-
- /*
- * In TLSv1.3 we have some post-processing to change cipher state, otherwise
- * we're done with this message
- */
- if (SSL_IS_TLS13(s)
- && (!s->method->ssl3_enc->setup_key_block(s)
- || !s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
- /* SSLfatal() already called */
- goto err;
- }
-
- OPENSSL_free(extensions);
- return MSG_PROCESS_CONTINUE_READING;
- err:
- OPENSSL_free(extensions);
- return MSG_PROCESS_ERROR;
-}
-
-static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s,
- PACKET *extpkt)
-{
- RAW_EXTENSION *extensions = NULL;
-
- /*
- * If we were sending early_data then the enc_write_ctx is now invalid and
- * should not be used.
- */
- EVP_CIPHER_CTX_free(s->enc_write_ctx);
- s->enc_write_ctx = NULL;
-
- if (!tls_collect_extensions(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
- &extensions, NULL, 1)
- || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
- extensions, NULL, 0, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- OPENSSL_free(extensions);
- extensions = NULL;
-
- if (s->ext.tls13_cookie_len == 0
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- && s->s3->tmp.pkey != NULL
-#endif
- ) {
- /*
- * We didn't receive a cookie or a new key_share so the next
- * ClientHello will not change
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST,
- SSL_R_NO_CHANGE_FOLLOWING_HRR);
- goto err;
- }
-
- /*
- * Re-initialise the Transcript Hash. We're going to prepopulate it with
- * a synthetic message_hash in place of ClientHello1.
- */
- if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /*
- * Add this message to the Transcript Hash. Normally this is done
- * automatically prior to the message processing stage. However due to the
- * need to create the synthetic message hash, we defer that step until now
- * for HRR messages.
- */
- if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->init_num + SSL3_HM_HEADER_LENGTH)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- return MSG_PROCESS_FINISHED_READING;
- err:
- OPENSSL_free(extensions);
- return MSG_PROCESS_ERROR;
-}
-
-MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
-{
- int i;
- MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
- unsigned long cert_list_len, cert_len;
- X509 *x = NULL;
- const unsigned char *certstart, *certbytes;
- STACK_OF(X509) *sk = NULL;
- EVP_PKEY *pkey = NULL;
- size_t chainidx, certidx;
- unsigned int context = 0;
- const SSL_CERT_LOOKUP *clu;
-
- if ((sk = sk_X509_new_null()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if ((SSL_IS_TLS13(s) && !PACKET_get_1(pkt, &context))
- || context != 0
- || !PACKET_get_net_3(pkt, &cert_list_len)
- || PACKET_remaining(pkt) != cert_list_len
- || PACKET_remaining(pkt) == 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- for (chainidx = 0; PACKET_remaining(pkt); chainidx++) {
- if (!PACKET_get_net_3(pkt, &cert_len)
- || !PACKET_get_bytes(pkt, &certbytes, cert_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
- goto err;
- }
-
- certstart = certbytes;
- x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
- if (x == NULL) {
- SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
- goto err;
- }
- if (certbytes != (certstart + cert_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
- goto err;
- }
-
- if (SSL_IS_TLS13(s)) {
- RAW_EXTENSION *rawexts = NULL;
- PACKET extensions;
-
- if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_BAD_LENGTH);
- goto err;
- }
- if (!tls_collect_extensions(s, &extensions,
- SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
- NULL, chainidx == 0)
- || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
- rawexts, x, chainidx,
- PACKET_remaining(pkt) == 0)) {
- OPENSSL_free(rawexts);
- /* SSLfatal already called */
- goto err;
- }
- OPENSSL_free(rawexts);
- }
-
- if (!sk_X509_push(sk, x)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- x = NULL;
- }
-
- i = ssl_verify_cert_chain(s, sk);
- /*
- * The documented interface is that SSL_VERIFY_PEER should be set in order
- * for client side verification of the server certificate to take place.
- * However, historically the code has only checked that *any* flag is set
- * to cause server verification to take place. Use of the other flags makes
- * no sense in client mode. An attempt to clean up the semantics was
- * reverted because at least one application *only* set
- * SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Prior to the clean up this still caused
- * server verification to take place, after the clean up it silently did
- * nothing. SSL_CTX_set_verify()/SSL_set_verify() cannot validate the flags
- * sent to them because they are void functions. Therefore, we now use the
- * (less clean) historic behaviour of performing validation if any flag is
- * set. The *documented* interface remains the same.
- */
- if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
- SSLfatal(s, ssl_x509err2alert(s->verify_result),
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_CERTIFICATE_VERIFY_FAILED);
- goto err;
- }
- ERR_clear_error(); /* but we keep s->verify_result */
- if (i > 1) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
- goto err;
- }
-
- s->session->peer_chain = sk;
- /*
- * Inconsistency alert: cert_chain does include the peer's certificate,
- * which we don't include in statem_srvr.c
- */
- x = sk_X509_value(sk, 0);
- sk = NULL;
-
- pkey = X509_get0_pubkey(x);
-
- if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
- x = NULL;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
- goto err;
- }
-
- if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
- x = NULL;
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- goto err;
- }
- /*
- * Check certificate type is consistent with ciphersuite. For TLS 1.3
- * skip check since TLS 1.3 ciphersuites can be used with any certificate
- * type.
- */
- if (!SSL_IS_TLS13(s)) {
- if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) {
- x = NULL;
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
- SSL_R_WRONG_CERTIFICATE_TYPE);
- goto err;
- }
- }
-
- X509_free(s->session->peer);
- X509_up_ref(x);
- s->session->peer = x;
- s->session->verify_result = s->verify_result;
- x = NULL;
-
- /* Save the current hash state for when we receive the CertificateVerify */
- if (SSL_IS_TLS13(s)
- && !ssl_handshake_hash(s, s->cert_verify_hash,
- sizeof(s->cert_verify_hash),
- &s->cert_verify_hash_len)) {
- /* SSLfatal() already called */;
- goto err;
- }
-
- ret = MSG_PROCESS_CONTINUE_READING;
-
- err:
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return ret;
-}
-
-static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
-{
-#ifndef OPENSSL_NO_PSK
- PACKET psk_identity_hint;
-
- /* PSK ciphersuites are preceded by an identity hint */
-
- if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- /*
- * Store PSK identity hint for later use, hint is used in
- * tls_construct_client_key_exchange. Assume that the maximum length of
- * a PSK identity hint can be as long as the maximum length of a PSK
- * identity.
- */
- if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return 0;
- }
-
- if (PACKET_remaining(&psk_identity_hint) == 0) {
- OPENSSL_free(s->session->psk_identity_hint);
- s->session->psk_identity_hint = NULL;
- } else if (!PACKET_strndup(&psk_identity_hint,
- &s->session->psk_identity_hint)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
-{
-#ifndef OPENSSL_NO_SRP
- PACKET prime, generator, salt, server_pub;
-
- if (!PACKET_get_length_prefixed_2(pkt, &prime)
- || !PACKET_get_length_prefixed_2(pkt, &generator)
- || !PACKET_get_length_prefixed_1(pkt, &salt)
- || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- /* TODO(size_t): Convert BN_bin2bn() calls */
- if ((s->srp_ctx.N =
- BN_bin2bn(PACKET_data(&prime),
- (int)PACKET_remaining(&prime), NULL)) == NULL
- || (s->srp_ctx.g =
- BN_bin2bn(PACKET_data(&generator),
- (int)PACKET_remaining(&generator), NULL)) == NULL
- || (s->srp_ctx.s =
- BN_bin2bn(PACKET_data(&salt),
- (int)PACKET_remaining(&salt), NULL)) == NULL
- || (s->srp_ctx.B =
- BN_bin2bn(PACKET_data(&server_pub),
- (int)PACKET_remaining(&server_pub), NULL)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
- ERR_R_BN_LIB);
- return 0;
- }
-
- if (!srp_verify_server_param(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /* We must check if there is a certificate */
- if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
- *pkey = X509_get0_pubkey(s->session->peer);
-
- return 1;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
-{
-#ifndef OPENSSL_NO_DH
- PACKET prime, generator, pub_key;
- EVP_PKEY *peer_tmp = NULL;
-
- DH *dh = NULL;
- BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
-
- int check_bits = 0;
-
- if (!PACKET_get_length_prefixed_2(pkt, &prime)
- || !PACKET_get_length_prefixed_2(pkt, &generator)
- || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- peer_tmp = EVP_PKEY_new();
- dh = DH_new();
-
- if (peer_tmp == NULL || dh == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* TODO(size_t): Convert these calls */
- p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL);
- g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator),
- NULL);
- bnpub_key = BN_bin2bn(PACKET_data(&pub_key),
- (int)PACKET_remaining(&pub_key), NULL);
- if (p == NULL || g == NULL || bnpub_key == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_BN_LIB);
- goto err;
- }
-
- /* test non-zero pubkey */
- if (BN_is_zero(bnpub_key)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
- SSL_R_BAD_DH_VALUE);
- goto err;
- }
-
- if (!DH_set0_pqg(dh, p, NULL, g)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_BN_LIB);
- goto err;
- }
- p = g = NULL;
-
- if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
- SSL_R_BAD_DH_VALUE);
- goto err;
- }
-
- if (!DH_set0_key(dh, bnpub_key, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_BN_LIB);
- goto err;
- }
- bnpub_key = NULL;
-
- if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_EVP_LIB);
- goto err;
- }
+ tsan_counter(&s->session_ctx->stats.sess_miss);
+ if (!ssl_get_new_session(s, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+
+ s->session->ssl_version = s->version;
+ /*
+ * In TLSv1.2 and below we save the session id we were sent so we can
+ * resume it later. In TLSv1.3 the session id we were sent is just an
+ * echo of what we originally sent in the ClientHello and should not be
+ * used for resumption.
+ */
+ if (!SSL_IS_TLS13(s)) {
+ s->session->session_id_length = session_id_len;
+ /* session_id_len could be 0 */
+ if (session_id_len > 0)
+ memcpy(s->session->session_id, PACKET_data(&session_id),
+ session_id_len);
+ }
+ }
+
+ /* Session version and negotiated protocol version should match */
+ if (s->version != s->session->ssl_version) {
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_SSL_SESSION_VERSION_MISMATCH);
+ goto err;
+ }
+ /*
+ * Now that we know the version, update the check to see if it's an allowed
+ * version.
+ */
+ s->s3->tmp.min_ver = s->version;
+ s->s3->tmp.max_ver = s->version;
+
+ if (!set_client_ciphersuite(s, cipherchars)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+#ifdef OPENSSL_NO_COMP
+ if (compression != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ goto err;
+ }
+ /*
+ * If compression is disabled we'd better not try to resume a session
+ * using compression.
+ */
+ if (s->session->compress_meth != 0) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_INCONSISTENT_COMPRESSION);
+ goto err;
+ }
+#else
+ if (s->hit && compression != s->session->compress_meth) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
+ goto err;
+ }
+ if (compression == 0)
+ comp = NULL;
+ else if (!ssl_allow_compression(s)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_COMPRESSION_DISABLED);
+ goto err;
+ } else {
+ comp = ssl3_comp_find(s->ctx->comp_methods, compression);
+ }
+
+ if (compression != 0 && comp == NULL) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ goto err;
+ } else {
+ s->s3->tmp.new_compression = comp;
+ }
+#endif
+
+ if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && s->hit) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+ size_t labellen;
+
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ /* Don't include the terminating zero. */
+ labellen = sizeof(labelbuffer) - 1;
+ if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+ labellen += 1;
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey),
+ labelbuffer,
+ labellen, NULL, 0, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ BIO_ctrl(SSL_get_wbio(s),
+ BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+#endif
+
+ /*
+ * In TLSv1.3 we have some post-processing to change cipher state, otherwise
+ * we're done with this message
+ */
+ if (SSL_IS_TLS13(s)
+ && (!s->method->ssl3_enc->setup_key_block(s)
+ || !s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ OPENSSL_free(extensions);
+ return MSG_PROCESS_CONTINUE_READING;
+ err:
+ OPENSSL_free(extensions);
+ return MSG_PROCESS_ERROR;
+}
+
+static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s,
+ PACKET *extpkt)
+{
+ RAW_EXTENSION *extensions = NULL;
+
+ /*
+ * If we were sending early_data then the enc_write_ctx is now invalid and
+ * should not be used.
+ */
+ EVP_CIPHER_CTX_free(s->enc_write_ctx);
+ s->enc_write_ctx = NULL;
+
+ if (!tls_collect_extensions(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
+ &extensions, NULL, 1)
+ || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
+ extensions, NULL, 0, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ OPENSSL_free(extensions);
+ extensions = NULL;
+
+ if (s->ext.tls13_cookie_len == 0
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ && s->s3->tmp.pkey != NULL
+#endif
+ ) {
+ /*
+ * We didn't receive a cookie or a new key_share so the next
+ * ClientHello will not change
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST,
+ SSL_R_NO_CHANGE_FOLLOWING_HRR);
+ goto err;
+ }
+
+ /*
+ * Re-initialise the Transcript Hash. We're going to prepopulate it with
+ * a synthetic message_hash in place of ClientHello1.
+ */
+ if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /*
+ * Add this message to the Transcript Hash. Normally this is done
+ * automatically prior to the message processing stage. However due to the
+ * need to create the synthetic message hash, we defer that step until now
+ * for HRR messages.
+ */
+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num + SSL3_HM_HEADER_LENGTH)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ return MSG_PROCESS_FINISHED_READING;
+ err:
+ OPENSSL_free(extensions);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
+{
+ int i;
+ MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
+ unsigned long cert_list_len, cert_len;
+ X509 *x = NULL;
+ const unsigned char *certstart, *certbytes;
+ STACK_OF(X509) *sk = NULL;
+ EVP_PKEY *pkey = NULL;
+ size_t chainidx, certidx;
+ unsigned int context = 0;
+ const SSL_CERT_LOOKUP *clu;
+
+ if ((sk = sk_X509_new_null()) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if ((SSL_IS_TLS13(s) && !PACKET_get_1(pkt, &context))
+ || context != 0
+ || !PACKET_get_net_3(pkt, &cert_list_len)
+ || PACKET_remaining(pkt) != cert_list_len
+ || PACKET_remaining(pkt) == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ for (chainidx = 0; PACKET_remaining(pkt); chainidx++) {
+ if (!PACKET_get_net_3(pkt, &cert_len)
+ || !PACKET_get_bytes(pkt, &certbytes, cert_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ certstart = certbytes;
+ x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
+ if (x == NULL) {
+ SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ if (certbytes != (certstart + cert_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (SSL_IS_TLS13(s)) {
+ RAW_EXTENSION *rawexts = NULL;
+ PACKET extensions;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_BAD_LENGTH);
+ goto err;
+ }
+ if (!tls_collect_extensions(s, &extensions,
+ SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
+ NULL, chainidx == 0)
+ || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
+ rawexts, x, chainidx,
+ PACKET_remaining(pkt) == 0)) {
+ OPENSSL_free(rawexts);
+ /* SSLfatal already called */
+ goto err;
+ }
+ OPENSSL_free(rawexts);
+ }
+
+ if (!sk_X509_push(sk, x)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
+
+ i = ssl_verify_cert_chain(s, sk);
+ /*
+ * The documented interface is that SSL_VERIFY_PEER should be set in order
+ * for client side verification of the server certificate to take place.
+ * However, historically the code has only checked that *any* flag is set
+ * to cause server verification to take place. Use of the other flags makes
+ * no sense in client mode. An attempt to clean up the semantics was
+ * reverted because at least one application *only* set
+ * SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Prior to the clean up this still caused
+ * server verification to take place, after the clean up it silently did
+ * nothing. SSL_CTX_set_verify()/SSL_set_verify() cannot validate the flags
+ * sent to them because they are void functions. Therefore, we now use the
+ * (less clean) historic behaviour of performing validation if any flag is
+ * set. The *documented* interface remains the same.
+ */
+ if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
+ SSLfatal(s, ssl_x509err2alert(s->verify_result),
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto err;
+ }
+ ERR_clear_error(); /* but we keep s->verify_result */
+ if (i > 1) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
+ goto err;
+ }
+
+ s->session->peer_chain = sk;
+ /*
+ * Inconsistency alert: cert_chain does include the peer's certificate,
+ * which we don't include in statem_srvr.c
+ */
+ x = sk_X509_value(sk, 0);
+ sk = NULL;
+
+ pkey = X509_get0_pubkey(x);
+
+ if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
+ x = NULL;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
+ goto err;
+ }
+
+ if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
+ x = NULL;
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto err;
+ }
+ /*
+ * Check certificate type is consistent with ciphersuite. For TLS 1.3
+ * skip check since TLS 1.3 ciphersuites can be used with any certificate
+ * type.
+ */
+ if (!SSL_IS_TLS13(s)) {
+ if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) {
+ x = NULL;
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+ SSL_R_WRONG_CERTIFICATE_TYPE);
+ goto err;
+ }
+ }
+
+ X509_free(s->session->peer);
+ X509_up_ref(x);
+ s->session->peer = x;
+ s->session->verify_result = s->verify_result;
+ x = NULL;
+
+ /* Save the current hash state for when we receive the CertificateVerify */
+ if (SSL_IS_TLS13(s)
+ && !ssl_handshake_hash(s, s->cert_verify_hash,
+ sizeof(s->cert_verify_hash),
+ &s->cert_verify_hash_len)) {
+ /* SSLfatal() already called */;
+ goto err;
+ }
+
+ ret = MSG_PROCESS_CONTINUE_READING;
+
+ err:
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_PSK
+ PACKET psk_identity_hint;
+
+ /* PSK ciphersuites are preceded by an identity hint */
+
+ if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /*
+ * Store PSK identity hint for later use, hint is used in
+ * tls_construct_client_key_exchange. Assume that the maximum length of
+ * a PSK identity hint can be as long as the maximum length of a PSK
+ * identity.
+ */
+ if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+
+ if (PACKET_remaining(&psk_identity_hint) == 0) {
+ OPENSSL_free(s->session->psk_identity_hint);
+ s->session->psk_identity_hint = NULL;
+ } else if (!PACKET_strndup(&psk_identity_hint,
+ &s->session->psk_identity_hint)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
+{
+#ifndef OPENSSL_NO_SRP
+ PACKET prime, generator, salt, server_pub;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &prime)
+ || !PACKET_get_length_prefixed_2(pkt, &generator)
+ || !PACKET_get_length_prefixed_1(pkt, &salt)
+ || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /* TODO(size_t): Convert BN_bin2bn() calls */
+ if ((s->srp_ctx.N =
+ BN_bin2bn(PACKET_data(&prime),
+ (int)PACKET_remaining(&prime), NULL)) == NULL
+ || (s->srp_ctx.g =
+ BN_bin2bn(PACKET_data(&generator),
+ (int)PACKET_remaining(&generator), NULL)) == NULL
+ || (s->srp_ctx.s =
+ BN_bin2bn(PACKET_data(&salt),
+ (int)PACKET_remaining(&salt), NULL)) == NULL
+ || (s->srp_ctx.B =
+ BN_bin2bn(PACKET_data(&server_pub),
+ (int)PACKET_remaining(&server_pub), NULL)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
+ ERR_R_BN_LIB);
+ return 0;
+ }
+
+ if (!srp_verify_server_param(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ /* We must check if there is a certificate */
+ if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
+ *pkey = X509_get0_pubkey(s->session->peer);
+
+ return 1;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
+{
+#ifndef OPENSSL_NO_DH
+ PACKET prime, generator, pub_key;
+ EVP_PKEY *peer_tmp = NULL;
+
+ DH *dh = NULL;
+ BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
+
+ int check_bits = 0;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &prime)
+ || !PACKET_get_length_prefixed_2(pkt, &generator)
+ || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ peer_tmp = EVP_PKEY_new();
+ dh = DH_new();
+
+ if (peer_tmp == NULL || dh == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* TODO(size_t): Convert these calls */
+ p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL);
+ g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator),
+ NULL);
+ bnpub_key = BN_bin2bn(PACKET_data(&pub_key),
+ (int)PACKET_remaining(&pub_key), NULL);
+ if (p == NULL || g == NULL || bnpub_key == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+ ERR_R_BN_LIB);
+ goto err;
+ }
+
+ /* test non-zero pubkey */
+ if (BN_is_zero(bnpub_key)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
+ SSL_R_BAD_DH_VALUE);
+ goto err;
+ }
+
+ if (!DH_set0_pqg(dh, p, NULL, g)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+ ERR_R_BN_LIB);
+ goto err;
+ }
+ p = g = NULL;
+
+ if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
+ SSL_R_BAD_DH_VALUE);
+ goto err;
+ }
+
+ if (!DH_set0_key(dh, bnpub_key, NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+ ERR_R_BN_LIB);
+ goto err;
+ }
+ bnpub_key = NULL;
+
+ if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
dh = NULL;
-
+
if (!ssl_security(s, SSL_SECOP_TMP_DH, EVP_PKEY_security_bits(peer_tmp),
0, peer_tmp)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SKE_DHE,
@@ -2159,1692 +2159,1692 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
goto err;
}
- s->s3->peer_tmp = peer_tmp;
-
- /*
- * FIXME: This makes assumptions about which ciphersuites come with
- * public keys. We should have a less ad-hoc way of doing this
- */
- if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
- *pkey = X509_get0_pubkey(s->session->peer);
- /* else anonymous DH, so no certificate or pkey. */
-
- return 1;
-
- err:
- BN_free(p);
- BN_free(g);
- BN_free(bnpub_key);
- DH_free(dh);
- EVP_PKEY_free(peer_tmp);
-
- return 0;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
-{
-#ifndef OPENSSL_NO_EC
- PACKET encoded_pt;
- unsigned int curve_type, curve_id;
-
- /*
- * Extract elliptic curve parameters and the server's ephemeral ECDH
- * public key. We only support named (not generic) curves and
- * ECParameters in this case is just three bytes.
- */
- if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_LENGTH_TOO_SHORT);
- return 0;
- }
- /*
- * Check curve is named curve type and one of our preferences, if not
- * server has sent an invalid curve.
- */
- if (curve_type != NAMED_CURVE_TYPE
- || !tls1_check_group_id(s, curve_id, 1)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_WRONG_CURVE);
- return 0;
- }
-
- if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
- return 0;
- }
-
- if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
- PACKET_data(&encoded_pt),
- PACKET_remaining(&encoded_pt))) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
- SSL_R_BAD_ECPOINT);
- return 0;
- }
-
- /*
- * The ECC/TLS specification does not mention the use of DSA to sign
- * ECParameters in the server key exchange message. We do support RSA
- * and ECDSA.
- */
- if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA)
- *pkey = X509_get0_pubkey(s->session->peer);
- else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aRSA)
- *pkey = X509_get0_pubkey(s->session->peer);
- /* else anonymous ECDH, so no certificate or pkey. */
-
- return 1;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
-{
- long alg_k;
- EVP_PKEY *pkey = NULL;
- EVP_MD_CTX *md_ctx = NULL;
- EVP_PKEY_CTX *pctx = NULL;
- PACKET save_param_start, signature;
-
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-
- save_param_start = *pkt;
-
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- EVP_PKEY_free(s->s3->peer_tmp);
- s->s3->peer_tmp = NULL;
-#endif
-
- if (alg_k & SSL_PSK) {
- if (!tls_process_ske_psk_preamble(s, pkt)) {
- /* SSLfatal() already called */
- goto err;
- }
- }
-
- /* Nothing else to do for plain PSK or RSAPSK */
- if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
- } else if (alg_k & SSL_kSRP) {
- if (!tls_process_ske_srp(s, pkt, &pkey)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
- if (!tls_process_ske_dhe(s, pkt, &pkey)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
- if (!tls_process_ske_ecdhe(s, pkt, &pkey)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_UNEXPECTED_MESSAGE);
- goto err;
- }
-
- /* if it was signed, check the signature */
- if (pkey != NULL) {
- PACKET params;
- int maxsig;
- const EVP_MD *md = NULL;
- unsigned char *tbs;
- size_t tbslen;
- int rv;
-
- /*
- * |pkt| now points to the beginning of the signature, so the difference
- * equals the length of the parameters.
- */
- if (!PACKET_get_sub_packet(&save_param_start, &params,
- PACKET_remaining(&save_param_start) -
- PACKET_remaining(pkt))) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (SSL_USE_SIGALGS(s)) {
- unsigned int sigalg;
-
- if (!PACKET_get_net_2(pkt, &sigalg)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_LENGTH_TOO_SHORT);
- goto err;
- }
- if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-#ifdef SSL_DEBUG
- if (SSL_USE_SIGALGS(s))
- fprintf(stderr, "USING TLSv1.2 HASH %s\n",
- md == NULL ? "n/a" : EVP_MD_name(md));
-#endif
-
- if (!PACKET_get_length_prefixed_2(pkt, &signature)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- maxsig = EVP_PKEY_size(pkey);
- if (maxsig < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * Check signature length
- */
- if (PACKET_remaining(&signature) > (size_t)maxsig) {
- /* wrong packet length */
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_WRONG_SIGNATURE_LENGTH);
- goto err;
- }
-
- md_ctx = EVP_MD_CTX_new();
- if (md_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_EVP_LIB);
- goto err;
- }
- if (SSL_USE_PSS(s)) {
- if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
- || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
- RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
- goto err;
- }
- }
- tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(&params),
- PACKET_remaining(&params));
- if (tbslen == 0) {
- /* SSLfatal() already called */
- goto err;
- }
-
- rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature),
- PACKET_remaining(&signature), tbs, tbslen);
- OPENSSL_free(tbs);
- if (rv <= 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_BAD_SIGNATURE);
- goto err;
- }
- EVP_MD_CTX_free(md_ctx);
- md_ctx = NULL;
- } else {
- /* aNULL, aSRP or PSK do not need public keys */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
- && !(alg_k & SSL_PSK)) {
- /* Might be wrong key type, check it */
- if (ssl3_check_cert_and_algorithm(s)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_BAD_DATA);
- }
- /* else this shouldn't happen, SSLfatal() already called */
- goto err;
- }
- /* still data left over */
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- SSL_R_EXTRA_DATA_IN_MESSAGE);
- goto err;
- }
- }
-
- return MSG_PROCESS_CONTINUE_READING;
- err:
- EVP_MD_CTX_free(md_ctx);
- return MSG_PROCESS_ERROR;
-}
-
-MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
-{
- size_t i;
-
- /* Clear certificate validity flags */
- for (i = 0; i < SSL_PKEY_NUM; i++)
- s->s3->tmp.valid_flags[i] = 0;
-
- if (SSL_IS_TLS13(s)) {
- PACKET reqctx, extensions;
- RAW_EXTENSION *rawexts = NULL;
-
- if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) {
- /*
- * We already sent close_notify. This can only happen in TLSv1.3
- * post-handshake messages. We can't reasonably respond to this, so
- * we just ignore it
- */
- return MSG_PROCESS_FINISHED_READING;
- }
-
- /* Free and zero certificate types: it is not present in TLS 1.3 */
- OPENSSL_free(s->s3->tmp.ctype);
- s->s3->tmp.ctype = NULL;
- s->s3->tmp.ctype_len = 0;
- OPENSSL_free(s->pha_context);
- s->pha_context = NULL;
+ s->s3->peer_tmp = peer_tmp;
+
+ /*
+ * FIXME: This makes assumptions about which ciphersuites come with
+ * public keys. We should have a less ad-hoc way of doing this
+ */
+ if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
+ *pkey = X509_get0_pubkey(s->session->peer);
+ /* else anonymous DH, so no certificate or pkey. */
+
+ return 1;
+
+ err:
+ BN_free(p);
+ BN_free(g);
+ BN_free(bnpub_key);
+ DH_free(dh);
+ EVP_PKEY_free(peer_tmp);
+
+ return 0;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
+{
+#ifndef OPENSSL_NO_EC
+ PACKET encoded_pt;
+ unsigned int curve_type, curve_id;
+
+ /*
+ * Extract elliptic curve parameters and the server's ephemeral ECDH
+ * public key. We only support named (not generic) curves and
+ * ECParameters in this case is just three bytes.
+ */
+ if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+ SSL_R_LENGTH_TOO_SHORT);
+ return 0;
+ }
+ /*
+ * Check curve is named curve type and one of our preferences, if not
+ * server has sent an invalid curve.
+ */
+ if (curve_type != NAMED_CURVE_TYPE
+ || !tls1_check_group_id(s, curve_id, 1)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
+ SSL_R_WRONG_CURVE);
+ return 0;
+ }
+
+ if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+ SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+ return 0;
+ }
+
+ if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
+ PACKET_data(&encoded_pt),
+ PACKET_remaining(&encoded_pt))) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
+ SSL_R_BAD_ECPOINT);
+ return 0;
+ }
+
+ /*
+ * The ECC/TLS specification does not mention the use of DSA to sign
+ * ECParameters in the server key exchange message. We do support RSA
+ * and ECDSA.
+ */
+ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA)
+ *pkey = X509_get0_pubkey(s->session->peer);
+ else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aRSA)
+ *pkey = X509_get0_pubkey(s->session->peer);
+ /* else anonymous ECDH, so no certificate or pkey. */
+
+ return 1;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
+{
+ long alg_k;
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX *md_ctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ PACKET save_param_start, signature;
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ save_param_start = *pkt;
+
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ EVP_PKEY_free(s->s3->peer_tmp);
+ s->s3->peer_tmp = NULL;
+#endif
+
+ if (alg_k & SSL_PSK) {
+ if (!tls_process_ske_psk_preamble(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+
+ /* Nothing else to do for plain PSK or RSAPSK */
+ if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_process_ske_srp(s, pkt, &pkey)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (!tls_process_ske_dhe(s, pkt, &pkey)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ if (!tls_process_ske_ecdhe(s, pkt, &pkey)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
+ /* if it was signed, check the signature */
+ if (pkey != NULL) {
+ PACKET params;
+ int maxsig;
+ const EVP_MD *md = NULL;
+ unsigned char *tbs;
+ size_t tbslen;
+ int rv;
+
+ /*
+ * |pkt| now points to the beginning of the signature, so the difference
+ * equals the length of the parameters.
+ */
+ if (!PACKET_get_sub_packet(&save_param_start, &params,
+ PACKET_remaining(&save_param_start) -
+ PACKET_remaining(pkt))) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ unsigned int sigalg;
+
+ if (!PACKET_get_net_2(pkt, &sigalg)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto err;
+ }
+ if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+#ifdef SSL_DEBUG
+ if (SSL_USE_SIGALGS(s))
+ fprintf(stderr, "USING TLSv1.2 HASH %s\n",
+ md == NULL ? "n/a" : EVP_MD_name(md));
+#endif
+
+ if (!PACKET_get_length_prefixed_2(pkt, &signature)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ maxsig = EVP_PKEY_size(pkey);
+ if (maxsig < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Check signature length
+ */
+ if (PACKET_remaining(&signature) > (size_t)maxsig) {
+ /* wrong packet length */
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_WRONG_SIGNATURE_LENGTH);
+ goto err;
+ }
+
+ md_ctx = EVP_MD_CTX_new();
+ if (md_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (SSL_USE_PSS(s)) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
+ || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
+ RSA_PSS_SALTLEN_DIGEST) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ goto err;
+ }
+ }
+ tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(&params),
+ PACKET_remaining(&params));
+ if (tbslen == 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature),
+ PACKET_remaining(&signature), tbs, tbslen);
+ OPENSSL_free(tbs);
+ if (rv <= 0) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_BAD_SIGNATURE);
+ goto err;
+ }
+ EVP_MD_CTX_free(md_ctx);
+ md_ctx = NULL;
+ } else {
+ /* aNULL, aSRP or PSK do not need public keys */
+ if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
+ && !(alg_k & SSL_PSK)) {
+ /* Might be wrong key type, check it */
+ if (ssl3_check_cert_and_algorithm(s)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_BAD_DATA);
+ }
+ /* else this shouldn't happen, SSLfatal() already called */
+ goto err;
+ }
+ /* still data left over */
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+ SSL_R_EXTRA_DATA_IN_MESSAGE);
+ goto err;
+ }
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+ err:
+ EVP_MD_CTX_free(md_ctx);
+ return MSG_PROCESS_ERROR;
+}
+
+MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
+{
+ size_t i;
+
+ /* Clear certificate validity flags */
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ s->s3->tmp.valid_flags[i] = 0;
+
+ if (SSL_IS_TLS13(s)) {
+ PACKET reqctx, extensions;
+ RAW_EXTENSION *rawexts = NULL;
+
+ if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) {
+ /*
+ * We already sent close_notify. This can only happen in TLSv1.3
+ * post-handshake messages. We can't reasonably respond to this, so
+ * we just ignore it
+ */
+ return MSG_PROCESS_FINISHED_READING;
+ }
+
+ /* Free and zero certificate types: it is not present in TLS 1.3 */
+ OPENSSL_free(s->s3->tmp.ctype);
+ s->s3->tmp.ctype = NULL;
+ s->s3->tmp.ctype_len = 0;
+ OPENSSL_free(s->pha_context);
+ s->pha_context = NULL;
s->pha_context_len = 0;
-
- if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
- !PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_BAD_LENGTH);
- return MSG_PROCESS_ERROR;
- }
- if (!tls_collect_extensions(s, &extensions,
- SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
- &rawexts, NULL, 1)
- || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
- rawexts, NULL, 0, 1)) {
- /* SSLfatal() already called */
- OPENSSL_free(rawexts);
- return MSG_PROCESS_ERROR;
- }
- OPENSSL_free(rawexts);
- if (!tls1_process_sigalgs(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_BAD_LENGTH);
- return MSG_PROCESS_ERROR;
- }
- } else {
- PACKET ctypes;
-
- /* get the certificate types */
- if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return MSG_PROCESS_ERROR;
- }
-
- if (SSL_USE_SIGALGS(s)) {
- PACKET sigalgs;
-
- if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- /*
- * Despite this being for certificates, preserve compatibility
- * with pre-TLS 1.3 and use the regular sigalgs field.
- */
- if (!tls1_save_sigalgs(s, &sigalgs, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_SIGNATURE_ALGORITHMS_ERROR);
- return MSG_PROCESS_ERROR;
- }
- if (!tls1_process_sigalgs(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- ERR_R_MALLOC_FAILURE);
- return MSG_PROCESS_ERROR;
- }
- }
-
- /* get the CA RDNs */
- if (!parse_ca_names(s, pkt)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
- }
-
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- /* we should setup a certificate to return.... */
- s->s3->tmp.cert_req = 1;
-
- /*
- * In TLSv1.3 we don't prepare the client certificate yet. We wait until
- * after the CertificateVerify message has been received. This is because
- * in TLSv1.3 the CertificateRequest arrives before the Certificate message
- * but in TLSv1.2 it is the other way around. We want to make sure that
- * SSL_get_peer_certificate() returns something sensible in
- * client_cert_cb.
- */
- if (SSL_IS_TLS13(s) && s->post_handshake_auth != SSL_PHA_REQUESTED)
- return MSG_PROCESS_CONTINUE_READING;
-
- return MSG_PROCESS_CONTINUE_PROCESSING;
-}
-
-MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
-{
- unsigned int ticklen;
- unsigned long ticket_lifetime_hint, age_add = 0;
- unsigned int sess_len;
- RAW_EXTENSION *exts = NULL;
- PACKET nonce;
-
- PACKET_null_init(&nonce);
-
- if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint)
- || (SSL_IS_TLS13(s)
- && (!PACKET_get_net_4(pkt, &age_add)
- || !PACKET_get_length_prefixed_1(pkt, &nonce)))
- || !PACKET_get_net_2(pkt, &ticklen)
- || (SSL_IS_TLS13(s) ? (ticklen == 0 || PACKET_remaining(pkt) < ticklen)
- : PACKET_remaining(pkt) != ticklen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- /*
- * Server is allowed to change its mind (in <=TLSv1.2) and send an empty
- * ticket. We already checked this TLSv1.3 case above, so it should never
- * be 0 here in that instance
- */
- if (ticklen == 0)
- return MSG_PROCESS_CONTINUE_READING;
-
- /*
- * Sessions must be immutable once they go into the session cache. Otherwise
- * we can get multi-thread problems. Therefore we don't "update" sessions,
- * we replace them with a duplicate. In TLSv1.3 we need to do this every
- * time a NewSessionTicket arrives because those messages arrive
- * post-handshake and the session may have already gone into the session
- * cache.
- */
- if (SSL_IS_TLS13(s) || s->session->session_id_length > 0) {
- SSL_SESSION *new_sess;
-
- /*
- * We reused an existing session, so we need to replace it with a new
- * one
- */
- if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if ((s->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) != 0
- && !SSL_IS_TLS13(s)) {
- /*
- * In TLSv1.2 and below the arrival of a new tickets signals that
- * any old ticket we were using is now out of date, so we remove the
- * old session from the cache. We carry on if this fails
- */
- SSL_CTX_remove_session(s->session_ctx, s->session);
- }
-
- SSL_SESSION_free(s->session);
- s->session = new_sess;
- }
-
- /*
- * Technically the cast to long here is not guaranteed by the C standard -
- * but we use it elsewhere, so this should be ok.
- */
- s->session->time = (long)time(NULL);
-
- OPENSSL_free(s->session->ext.tick);
- s->session->ext.tick = NULL;
- s->session->ext.ticklen = 0;
-
- s->session->ext.tick = OPENSSL_malloc(ticklen);
- if (s->session->ext.tick == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- s->session->ext.tick_lifetime_hint = ticket_lifetime_hint;
- s->session->ext.tick_age_add = age_add;
- s->session->ext.ticklen = ticklen;
-
- if (SSL_IS_TLS13(s)) {
- PACKET extpkt;
-
- if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!tls_collect_extensions(s, &extpkt,
- SSL_EXT_TLS1_3_NEW_SESSION_TICKET, &exts,
- NULL, 1)
- || !tls_parse_all_extensions(s,
- SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
- exts, NULL, 0, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
- }
-
- /*
- * There are two ways to detect a resumed ticket session. One is to set
- * an appropriate session ID and then the server must return a match in
- * ServerHello. This allows the normal client session ID matching to work
- * and we know much earlier that the ticket has been accepted. The
- * other way is to set zero length session ID when the ticket is
- * presented and rely on the handshake to determine session resumption.
- * We choose the former approach because this fits in with assumptions
- * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
- * SHA256 is disabled) hash of the ticket.
- */
- /*
- * TODO(size_t): we use sess_len here because EVP_Digest expects an int
- * but s->session->session_id_length is a size_t
- */
- if (!EVP_Digest(s->session->ext.tick, ticklen,
- s->session->session_id, &sess_len,
- EVP_sha256(), NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_EVP_LIB);
- goto err;
- }
- s->session->session_id_length = sess_len;
- s->session->not_resumable = 0;
-
- /* This is a standalone message in TLSv1.3, so there is no more to read */
- if (SSL_IS_TLS13(s)) {
- const EVP_MD *md = ssl_handshake_md(s);
- int hashleni = EVP_MD_size(md);
- size_t hashlen;
- static const unsigned char nonce_label[] = "resumption";
-
- /* Ensure cast to size_t is safe */
- if (!ossl_assert(hashleni >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- hashlen = (size_t)hashleni;
-
- if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
- nonce_label,
- sizeof(nonce_label) - 1,
- PACKET_data(&nonce),
- PACKET_remaining(&nonce),
- s->session->master_key,
- hashlen, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
- s->session->master_key_length = hashlen;
-
- OPENSSL_free(exts);
- ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
- return MSG_PROCESS_FINISHED_READING;
- }
-
- return MSG_PROCESS_CONTINUE_READING;
- err:
- OPENSSL_free(exts);
- return MSG_PROCESS_ERROR;
-}
-
-/*
- * In TLSv1.3 this is called from the extensions code, otherwise it is used to
- * parse a separate message. Returns 1 on success or 0 on failure
- */
-int tls_process_cert_status_body(SSL *s, PACKET *pkt)
-{
- size_t resplen;
- unsigned int type;
-
- if (!PACKET_get_1(pkt, &type)
- || type != TLSEXT_STATUSTYPE_ocsp) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- SSL_R_UNSUPPORTED_STATUS_TYPE);
- return 0;
- }
- if (!PACKET_get_net_3_len(pkt, &resplen)
- || PACKET_remaining(pkt) != resplen) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
- s->ext.ocsp.resp = OPENSSL_malloc(resplen);
- if (s->ext.ocsp.resp == NULL) {
+
+ if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
+ !PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_BAD_LENGTH);
+ return MSG_PROCESS_ERROR;
+ }
+ if (!tls_collect_extensions(s, &extensions,
+ SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
+ &rawexts, NULL, 1)
+ || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
+ rawexts, NULL, 0, 1)) {
+ /* SSLfatal() already called */
+ OPENSSL_free(rawexts);
+ return MSG_PROCESS_ERROR;
+ }
+ OPENSSL_free(rawexts);
+ if (!tls1_process_sigalgs(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_BAD_LENGTH);
+ return MSG_PROCESS_ERROR;
+ }
+ } else {
+ PACKET ctypes;
+
+ /* get the certificate types */
+ if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ PACKET sigalgs;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /*
+ * Despite this being for certificates, preserve compatibility
+ * with pre-TLS 1.3 and use the regular sigalgs field.
+ */
+ if (!tls1_save_sigalgs(s, &sigalgs, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_SIGNATURE_ALGORITHMS_ERROR);
+ return MSG_PROCESS_ERROR;
+ }
+ if (!tls1_process_sigalgs(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ ERR_R_MALLOC_FAILURE);
+ return MSG_PROCESS_ERROR;
+ }
+ }
+
+ /* get the CA RDNs */
+ if (!parse_ca_names(s, pkt)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+ }
+
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /* we should setup a certificate to return.... */
+ s->s3->tmp.cert_req = 1;
+
+ /*
+ * In TLSv1.3 we don't prepare the client certificate yet. We wait until
+ * after the CertificateVerify message has been received. This is because
+ * in TLSv1.3 the CertificateRequest arrives before the Certificate message
+ * but in TLSv1.2 it is the other way around. We want to make sure that
+ * SSL_get_peer_certificate() returns something sensible in
+ * client_cert_cb.
+ */
+ if (SSL_IS_TLS13(s) && s->post_handshake_auth != SSL_PHA_REQUESTED)
+ return MSG_PROCESS_CONTINUE_READING;
+
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+}
+
+MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
+{
+ unsigned int ticklen;
+ unsigned long ticket_lifetime_hint, age_add = 0;
+ unsigned int sess_len;
+ RAW_EXTENSION *exts = NULL;
+ PACKET nonce;
+
+ PACKET_null_init(&nonce);
+
+ if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint)
+ || (SSL_IS_TLS13(s)
+ && (!PACKET_get_net_4(pkt, &age_add)
+ || !PACKET_get_length_prefixed_1(pkt, &nonce)))
+ || !PACKET_get_net_2(pkt, &ticklen)
+ || (SSL_IS_TLS13(s) ? (ticklen == 0 || PACKET_remaining(pkt) < ticklen)
+ : PACKET_remaining(pkt) != ticklen)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /*
+ * Server is allowed to change its mind (in <=TLSv1.2) and send an empty
+ * ticket. We already checked this TLSv1.3 case above, so it should never
+ * be 0 here in that instance
+ */
+ if (ticklen == 0)
+ return MSG_PROCESS_CONTINUE_READING;
+
+ /*
+ * Sessions must be immutable once they go into the session cache. Otherwise
+ * we can get multi-thread problems. Therefore we don't "update" sessions,
+ * we replace them with a duplicate. In TLSv1.3 we need to do this every
+ * time a NewSessionTicket arrives because those messages arrive
+ * post-handshake and the session may have already gone into the session
+ * cache.
+ */
+ if (SSL_IS_TLS13(s) || s->session->session_id_length > 0) {
+ SSL_SESSION *new_sess;
+
+ /*
+ * We reused an existing session, so we need to replace it with a new
+ * one
+ */
+ if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if ((s->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) != 0
+ && !SSL_IS_TLS13(s)) {
+ /*
+ * In TLSv1.2 and below the arrival of a new tickets signals that
+ * any old ticket we were using is now out of date, so we remove the
+ * old session from the cache. We carry on if this fails
+ */
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ }
+
+ SSL_SESSION_free(s->session);
+ s->session = new_sess;
+ }
+
+ /*
+ * Technically the cast to long here is not guaranteed by the C standard -
+ * but we use it elsewhere, so this should be ok.
+ */
+ s->session->time = (long)time(NULL);
+
+ OPENSSL_free(s->session->ext.tick);
+ s->session->ext.tick = NULL;
+ s->session->ext.ticklen = 0;
+
+ s->session->ext.tick = OPENSSL_malloc(ticklen);
+ if (s->session->ext.tick == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ s->session->ext.tick_lifetime_hint = ticket_lifetime_hint;
+ s->session->ext.tick_age_add = age_add;
+ s->session->ext.ticklen = ticklen;
+
+ if (SSL_IS_TLS13(s)) {
+ PACKET extpkt;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!tls_collect_extensions(s, &extpkt,
+ SSL_EXT_TLS1_3_NEW_SESSION_TICKET, &exts,
+ NULL, 1)
+ || !tls_parse_all_extensions(s,
+ SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
+ exts, NULL, 0, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+
+ /*
+ * There are two ways to detect a resumed ticket session. One is to set
+ * an appropriate session ID and then the server must return a match in
+ * ServerHello. This allows the normal client session ID matching to work
+ * and we know much earlier that the ticket has been accepted. The
+ * other way is to set zero length session ID when the ticket is
+ * presented and rely on the handshake to determine session resumption.
+ * We choose the former approach because this fits in with assumptions
+ * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
+ * SHA256 is disabled) hash of the ticket.
+ */
+ /*
+ * TODO(size_t): we use sess_len here because EVP_Digest expects an int
+ * but s->session->session_id_length is a size_t
+ */
+ if (!EVP_Digest(s->session->ext.tick, ticklen,
+ s->session->session_id, &sess_len,
+ EVP_sha256(), NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ s->session->session_id_length = sess_len;
+ s->session->not_resumable = 0;
+
+ /* This is a standalone message in TLSv1.3, so there is no more to read */
+ if (SSL_IS_TLS13(s)) {
+ const EVP_MD *md = ssl_handshake_md(s);
+ int hashleni = EVP_MD_size(md);
+ size_t hashlen;
+ static const unsigned char nonce_label[] = "resumption";
+
+ /* Ensure cast to size_t is safe */
+ if (!ossl_assert(hashleni >= 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hashlen = (size_t)hashleni;
+
+ if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
+ nonce_label,
+ sizeof(nonce_label) - 1,
+ PACKET_data(&nonce),
+ PACKET_remaining(&nonce),
+ s->session->master_key,
+ hashlen, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ s->session->master_key_length = hashlen;
+
+ OPENSSL_free(exts);
+ ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
+ return MSG_PROCESS_FINISHED_READING;
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+ err:
+ OPENSSL_free(exts);
+ return MSG_PROCESS_ERROR;
+}
+
+/*
+ * In TLSv1.3 this is called from the extensions code, otherwise it is used to
+ * parse a separate message. Returns 1 on success or 0 on failure
+ */
+int tls_process_cert_status_body(SSL *s, PACKET *pkt)
+{
+ size_t resplen;
+ unsigned int type;
+
+ if (!PACKET_get_1(pkt, &type)
+ || type != TLSEXT_STATUSTYPE_ocsp) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+ SSL_R_UNSUPPORTED_STATUS_TYPE);
+ return 0;
+ }
+ if (!PACKET_get_net_3_len(pkt, &resplen)
+ || PACKET_remaining(pkt) != resplen) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ s->ext.ocsp.resp = OPENSSL_malloc(resplen);
+ if (s->ext.ocsp.resp == NULL) {
s->ext.ocsp.resp_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
s->ext.ocsp.resp_len = resplen;
- if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
-
- return 1;
-}
-
-
-MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
-{
- if (!tls_process_cert_status_body(s, pkt)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
-
- return MSG_PROCESS_CONTINUE_READING;
-}
-
-/*
- * Perform miscellaneous checks and processing after we have received the
- * server's initial flight. In TLS1.3 this is after the Server Finished message.
- * In <=TLS1.2 this is after the ServerDone message. Returns 1 on success or 0
- * on failure.
- */
-int tls_process_initial_server_flight(SSL *s)
-{
- /*
- * at this point we check that we have the required stuff from
- * the server
- */
- if (!ssl3_check_cert_and_algorithm(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /*
- * Call the ocsp status callback if needed. The |ext.ocsp.resp| and
- * |ext.ocsp.resp_len| values will be set if we actually received a status
- * message, or NULL and -1 otherwise
- */
- if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing
- && s->ctx->ext.status_cb != NULL) {
- int ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
-
- if (ret == 0) {
- SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE,
- SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
- SSL_R_INVALID_STATUS_RESPONSE);
- return 0;
- }
- if (ret < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
+ if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
+{
+ if (!tls_process_cert_status_body(s, pkt)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+}
+
+/*
+ * Perform miscellaneous checks and processing after we have received the
+ * server's initial flight. In TLS1.3 this is after the Server Finished message.
+ * In <=TLS1.2 this is after the ServerDone message. Returns 1 on success or 0
+ * on failure.
+ */
+int tls_process_initial_server_flight(SSL *s)
+{
+ /*
+ * at this point we check that we have the required stuff from
+ * the server
+ */
+ if (!ssl3_check_cert_and_algorithm(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ /*
+ * Call the ocsp status callback if needed. The |ext.ocsp.resp| and
+ * |ext.ocsp.resp_len| values will be set if we actually received a status
+ * message, or NULL and -1 otherwise
+ */
+ if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing
+ && s->ctx->ext.status_cb != NULL) {
+ int ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
+
+ if (ret == 0) {
+ SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE,
+ SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
+ SSL_R_INVALID_STATUS_RESPONSE);
+ return 0;
+ }
+ if (ret < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
SSL_R_OCSP_CALLBACK_FAILURE);
- return 0;
- }
- }
-#ifndef OPENSSL_NO_CT
- if (s->ct_validation_callback != NULL) {
- /* Note we validate the SCTs whether or not we abort on error */
- if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
-#endif
-
- return 1;
-}
-
-MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
-{
- if (PACKET_remaining(pkt) > 0) {
- /* should contain no data */
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-#ifndef OPENSSL_NO_SRP
- if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
- if (SRP_Calc_A_param(s) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
- SSL_R_SRP_A_CALC);
- return MSG_PROCESS_ERROR;
- }
- }
-#endif
-
- if (!tls_process_initial_server_flight(s)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
-
- return MSG_PROCESS_FINISHED_READING;
-}
-
-static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
-{
-#ifndef OPENSSL_NO_PSK
- int ret = 0;
- /*
- * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a
- * \0-terminated identity. The last byte is for us for simulating
- * strnlen.
- */
- char identity[PSK_MAX_IDENTITY_LEN + 1];
- size_t identitylen = 0;
- unsigned char psk[PSK_MAX_PSK_LEN];
- unsigned char *tmppsk = NULL;
- char *tmpidentity = NULL;
- size_t psklen = 0;
-
- if (s->psk_client_callback == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- SSL_R_PSK_NO_CLIENT_CB);
- goto err;
- }
-
- memset(identity, 0, sizeof(identity));
-
- psklen = s->psk_client_callback(s, s->session->psk_identity_hint,
- identity, sizeof(identity) - 1,
- psk, sizeof(psk));
-
- if (psklen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+#ifndef OPENSSL_NO_CT
+ if (s->ct_validation_callback != NULL) {
+ /* Note we validate the SCTs whether or not we abort on error */
+ if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+#endif
+
+ return 1;
+}
+
+MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
+{
+ if (PACKET_remaining(pkt) > 0) {
+ /* should contain no data */
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+#ifndef OPENSSL_NO_SRP
+ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if (SRP_Calc_A_param(s) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
+ SSL_R_SRP_A_CALC);
+ return MSG_PROCESS_ERROR;
+ }
+ }
+#endif
+
+ if (!tls_process_initial_server_flight(s)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+
+ return MSG_PROCESS_FINISHED_READING;
+}
+
+static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_PSK
+ int ret = 0;
+ /*
+ * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a
+ * \0-terminated identity. The last byte is for us for simulating
+ * strnlen.
+ */
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ size_t identitylen = 0;
+ unsigned char psk[PSK_MAX_PSK_LEN];
+ unsigned char *tmppsk = NULL;
+ char *tmpidentity = NULL;
+ size_t psklen = 0;
+
+ if (s->psk_client_callback == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+ SSL_R_PSK_NO_CLIENT_CB);
+ goto err;
+ }
+
+ memset(identity, 0, sizeof(identity));
+
+ psklen = s->psk_client_callback(s, s->session->psk_identity_hint,
+ identity, sizeof(identity) - 1,
+ psk, sizeof(psk));
+
+ if (psklen > PSK_MAX_PSK_LEN) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
psklen = PSK_MAX_PSK_LEN; /* Avoid overrunning the array on cleanse */
- goto err;
- } else if (psklen == 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- SSL_R_PSK_IDENTITY_NOT_FOUND);
- goto err;
- }
-
- identitylen = strlen(identity);
- if (identitylen > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- tmppsk = OPENSSL_memdup(psk, psklen);
- tmpidentity = OPENSSL_strdup(identity);
- if (tmppsk == NULL || tmpidentity == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- OPENSSL_free(s->s3->tmp.psk);
- s->s3->tmp.psk = tmppsk;
- s->s3->tmp.psklen = psklen;
- tmppsk = NULL;
- OPENSSL_free(s->session->psk_identity);
- s->session->psk_identity = tmpidentity;
- tmpidentity = NULL;
-
- if (!WPACKET_sub_memcpy_u16(pkt, identity, identitylen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- ret = 1;
-
- err:
- OPENSSL_cleanse(psk, psklen);
- OPENSSL_cleanse(identity, sizeof(identity));
- OPENSSL_clear_free(tmppsk, psklen);
- OPENSSL_clear_free(tmpidentity, identitylen);
-
- return ret;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
-{
-#ifndef OPENSSL_NO_RSA
- unsigned char *encdata = NULL;
- EVP_PKEY *pkey = NULL;
- EVP_PKEY_CTX *pctx = NULL;
- size_t enclen;
- unsigned char *pms = NULL;
- size_t pmslen = 0;
-
- if (s->session->peer == NULL) {
- /*
- * We should always have a server certificate with SSL_kRSA.
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- pkey = X509_get0_pubkey(s->session->peer);
- if (EVP_PKEY_get0_RSA(pkey) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- pmslen = SSL_MAX_MASTER_KEY_LENGTH;
- pms = OPENSSL_malloc(pmslen);
- if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- pms[0] = s->client_version >> 8;
- pms[1] = s->client_version & 0xff;
- /* TODO(size_t): Convert this function */
- if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Fix buf for TLS and beyond */
- if (s->version > SSL3_VERSION && !WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
- || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_EVP_LIB);
- goto err;
- }
- if (!WPACKET_allocate_bytes(pkt, enclen, &encdata)
- || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- SSL_R_BAD_RSA_ENCRYPT);
- goto err;
- }
- EVP_PKEY_CTX_free(pctx);
- pctx = NULL;
-
- /* Fix buf for TLS and beyond */
- if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Log the premaster secret, if logging is enabled. */
- if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- s->s3->tmp.pms = pms;
- s->s3->tmp.pmslen = pmslen;
-
- return 1;
- err:
- OPENSSL_clear_free(pms, pmslen);
- EVP_PKEY_CTX_free(pctx);
-
- return 0;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
-{
-#ifndef OPENSSL_NO_DH
- DH *dh_clnt = NULL;
- const BIGNUM *pub_key;
- EVP_PKEY *ckey = NULL, *skey = NULL;
- unsigned char *keybytes = NULL;
-
- skey = s->s3->peer_tmp;
- if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- ckey = ssl_generate_pkey(skey);
- if (ckey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- dh_clnt = EVP_PKEY_get0_DH(ckey);
-
- if (dh_clnt == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (ssl_derive(s, ckey, skey, 0) == 0) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /* send off the data */
- DH_get0_key(dh_clnt, &pub_key, NULL);
- if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key),
- &keybytes)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- BN_bn2bin(pub_key, keybytes);
- EVP_PKEY_free(ckey);
-
- return 1;
- err:
- EVP_PKEY_free(ckey);
- return 0;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
-{
-#ifndef OPENSSL_NO_EC
- unsigned char *encodedPoint = NULL;
- size_t encoded_pt_len = 0;
- EVP_PKEY *ckey = NULL, *skey = NULL;
- int ret = 0;
-
- skey = s->s3->peer_tmp;
- if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- ckey = ssl_generate_pkey(skey);
- if (ckey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (ssl_derive(s, ckey, skey, 0) == 0) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /* Generate encoding of client key */
- encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint);
-
- if (encoded_pt_len == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_EC_LIB);
- goto err;
- }
-
- if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- ret = 1;
- err:
- OPENSSL_free(encodedPoint);
- EVP_PKEY_free(ckey);
- return ret;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
-{
-#ifndef OPENSSL_NO_GOST
- /* GOST key exchange message creation */
- EVP_PKEY_CTX *pkey_ctx = NULL;
- X509 *peer_cert;
- size_t msglen;
- unsigned int md_len;
- unsigned char shared_ukm[32], tmp[256];
- EVP_MD_CTX *ukm_hash = NULL;
- int dgst_nid = NID_id_GostR3411_94;
- unsigned char *pms = NULL;
- size_t pmslen = 0;
-
- if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
- dgst_nid = NID_id_GostR3411_2012_256;
-
- /*
- * Get server certificate PKEY and create ctx from it
- */
- peer_cert = s->session->peer;
- if (!peer_cert) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
- return 0;
- }
-
- pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
- if (pkey_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
- /*
- * If we have send a certificate, and certificate key
- * parameters match those of server certificate, use
- * certificate key for key exchange
- */
-
- /* Otherwise, generate ephemeral key pair */
- pmslen = 32;
- pms = OPENSSL_malloc(pmslen);
- if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
- /* Generate session key
- * TODO(size_t): Convert this function
- */
- || RAND_bytes(pms, (int)pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
- goto err;
- };
- /*
- * Compute shared IV and store it in algorithm-specific context
- * data
- */
- ukm_hash = EVP_MD_CTX_new();
- if (ukm_hash == NULL
- || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
- || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
- SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
- SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- EVP_MD_CTX_free(ukm_hash);
- ukm_hash = NULL;
- if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
- EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- SSL_R_LIBRARY_BUG);
- goto err;
- }
- /* Make GOST keytransport blob message */
- /*
- * Encapsulate it into sequence
- */
- msglen = 255;
- if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- SSL_R_LIBRARY_BUG);
- goto err;
- }
-
- if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
- || (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81))
- || !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- EVP_PKEY_CTX_free(pkey_ctx);
- s->s3->tmp.pms = pms;
- s->s3->tmp.pmslen = pmslen;
-
- return 1;
- err:
- EVP_PKEY_CTX_free(pkey_ctx);
- OPENSSL_clear_free(pms, pmslen);
- EVP_MD_CTX_free(ukm_hash);
- return 0;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
-{
-#ifndef OPENSSL_NO_SRP
- unsigned char *abytes = NULL;
-
- if (s->srp_ctx.A == NULL
- || !WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(s->srp_ctx.A),
- &abytes)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- BN_bn2bin(s->srp_ctx.A, abytes);
-
- OPENSSL_free(s->session->srp_username);
- s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
- if (s->session->srp_username == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- return 1;
-#else
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
-{
- unsigned long alg_k;
-
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-
- /*
- * All of the construct functions below call SSLfatal() if necessary so
- * no need to do so here.
- */
- if ((alg_k & SSL_PSK)
- && !tls_construct_cke_psk_preamble(s, pkt))
- goto err;
-
- if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
- if (!tls_construct_cke_rsa(s, pkt))
- goto err;
- } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
- if (!tls_construct_cke_dhe(s, pkt))
- goto err;
- } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
- if (!tls_construct_cke_ecdhe(s, pkt))
- goto err;
- } else if (alg_k & SSL_kGOST) {
- if (!tls_construct_cke_gost(s, pkt))
- goto err;
- } else if (alg_k & SSL_kSRP) {
- if (!tls_construct_cke_srp(s, pkt))
- goto err;
- } else if (!(alg_k & SSL_kPSK)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- return 1;
- err:
- OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
- s->s3->tmp.pms = NULL;
+ goto err;
+ } else if (psklen == 0) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ goto err;
+ }
+
+ identitylen = strlen(identity);
+ if (identitylen > PSK_MAX_IDENTITY_LEN) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ tmppsk = OPENSSL_memdup(psk, psklen);
+ tmpidentity = OPENSSL_strdup(identity);
+ if (tmppsk == NULL || tmpidentity == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ OPENSSL_free(s->s3->tmp.psk);
+ s->s3->tmp.psk = tmppsk;
+ s->s3->tmp.psklen = psklen;
+ tmppsk = NULL;
+ OPENSSL_free(s->session->psk_identity);
+ s->session->psk_identity = tmpidentity;
+ tmpidentity = NULL;
+
+ if (!WPACKET_sub_memcpy_u16(pkt, identity, identitylen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = 1;
+
+ err:
+ OPENSSL_cleanse(psk, psklen);
+ OPENSSL_cleanse(identity, sizeof(identity));
+ OPENSSL_clear_free(tmppsk, psklen);
+ OPENSSL_clear_free(tmpidentity, identitylen);
+
+ return ret;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_RSA
+ unsigned char *encdata = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ size_t enclen;
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+
+ if (s->session->peer == NULL) {
+ /*
+ * We should always have a server certificate with SSL_kRSA.
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ pkey = X509_get0_pubkey(s->session->peer);
+ if (EVP_PKEY_get0_RSA(pkey) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ pmslen = SSL_MAX_MASTER_KEY_LENGTH;
+ pms = OPENSSL_malloc(pmslen);
+ if (pms == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ pms[0] = s->client_version >> 8;
+ pms[1] = s->client_version & 0xff;
+ /* TODO(size_t): Convert this function */
+ if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Fix buf for TLS and beyond */
+ if (s->version > SSL3_VERSION && !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
+ || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (!WPACKET_allocate_bytes(pkt, enclen, &encdata)
+ || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ SSL_R_BAD_RSA_ENCRYPT);
+ goto err;
+ }
+ EVP_PKEY_CTX_free(pctx);
+ pctx = NULL;
+
+ /* Fix buf for TLS and beyond */
+ if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Log the premaster secret, if logging is enabled. */
+ if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ s->s3->tmp.pms = pms;
+ s->s3->tmp.pmslen = pmslen;
+
+ return 1;
+ err:
+ OPENSSL_clear_free(pms, pmslen);
+ EVP_PKEY_CTX_free(pctx);
+
+ return 0;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_DH
+ DH *dh_clnt = NULL;
+ const BIGNUM *pub_key;
+ EVP_PKEY *ckey = NULL, *skey = NULL;
+ unsigned char *keybytes = NULL;
+
+ skey = s->s3->peer_tmp;
+ if (skey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ckey = ssl_generate_pkey(skey);
+ if (ckey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ dh_clnt = EVP_PKEY_get0_DH(ckey);
+
+ if (dh_clnt == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (ssl_derive(s, ckey, skey, 0) == 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /* send off the data */
+ DH_get0_key(dh_clnt, &pub_key, NULL);
+ if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key),
+ &keybytes)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ BN_bn2bin(pub_key, keybytes);
+ EVP_PKEY_free(ckey);
+
+ return 1;
+ err:
+ EVP_PKEY_free(ckey);
+ return 0;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_EC
+ unsigned char *encodedPoint = NULL;
+ size_t encoded_pt_len = 0;
+ EVP_PKEY *ckey = NULL, *skey = NULL;
+ int ret = 0;
+
+ skey = s->s3->peer_tmp;
+ if (skey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ckey = ssl_generate_pkey(skey);
+ if (ckey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (ssl_derive(s, ckey, skey, 0) == 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /* Generate encoding of client key */
+ encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint);
+
+ if (encoded_pt_len == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+ ERR_R_EC_LIB);
+ goto err;
+ }
+
+ if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ret = 1;
+ err:
+ OPENSSL_free(encodedPoint);
+ EVP_PKEY_free(ckey);
+ return ret;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_GOST
+ /* GOST key exchange message creation */
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ X509 *peer_cert;
+ size_t msglen;
+ unsigned int md_len;
+ unsigned char shared_ukm[32], tmp[256];
+ EVP_MD_CTX *ukm_hash = NULL;
+ int dgst_nid = NID_id_GostR3411_94;
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+
+ if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
+ dgst_nid = NID_id_GostR3411_2012_256;
+
+ /*
+ * Get server certificate PKEY and create ctx from it
+ */
+ peer_cert = s->session->peer;
+ if (!peer_cert) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+ return 0;
+ }
+
+ pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
+ if (pkey_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /*
+ * If we have send a certificate, and certificate key
+ * parameters match those of server certificate, use
+ * certificate key for key exchange
+ */
+
+ /* Otherwise, generate ephemeral key pair */
+ pmslen = 32;
+ pms = OPENSSL_malloc(pmslen);
+ if (pms == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
+ /* Generate session key
+ * TODO(size_t): Convert this function
+ */
+ || RAND_bytes(pms, (int)pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ };
+ /*
+ * Compute shared IV and store it in algorithm-specific context
+ * data
+ */
+ ukm_hash = EVP_MD_CTX_new();
+ if (ukm_hash == NULL
+ || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
+ || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ EVP_MD_CTX_free(ukm_hash);
+ ukm_hash = NULL;
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+ EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+ /* Make GOST keytransport blob message */
+ /*
+ * Encapsulate it into sequence
+ */
+ msglen = 255;
+ if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+
+ if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
+ || (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81))
+ || !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ EVP_PKEY_CTX_free(pkey_ctx);
+ s->s3->tmp.pms = pms;
+ s->s3->tmp.pmslen = pmslen;
+
+ return 1;
+ err:
+ EVP_PKEY_CTX_free(pkey_ctx);
+ OPENSSL_clear_free(pms, pmslen);
+ EVP_MD_CTX_free(ukm_hash);
+ return 0;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_SRP
+ unsigned char *abytes = NULL;
+
+ if (s->srp_ctx.A == NULL
+ || !WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(s->srp_ctx.A),
+ &abytes)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ BN_bn2bin(s->srp_ctx.A, abytes);
+
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+#else
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
+{
+ unsigned long alg_k;
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ /*
+ * All of the construct functions below call SSLfatal() if necessary so
+ * no need to do so here.
+ */
+ if ((alg_k & SSL_PSK)
+ && !tls_construct_cke_psk_preamble(s, pkt))
+ goto err;
+
+ if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
+ if (!tls_construct_cke_rsa(s, pkt))
+ goto err;
+ } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (!tls_construct_cke_dhe(s, pkt))
+ goto err;
+ } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ if (!tls_construct_cke_ecdhe(s, pkt))
+ goto err;
+ } else if (alg_k & SSL_kGOST) {
+ if (!tls_construct_cke_gost(s, pkt))
+ goto err;
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_construct_cke_srp(s, pkt))
+ goto err;
+ } else if (!(alg_k & SSL_kPSK)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ return 1;
+ err:
+ OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
+ s->s3->tmp.pms = NULL;
s->s3->tmp.pmslen = 0;
-#ifndef OPENSSL_NO_PSK
- OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
- s->s3->tmp.psk = NULL;
+#ifndef OPENSSL_NO_PSK
+ OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
+ s->s3->tmp.psk = NULL;
s->s3->tmp.psklen = 0;
-#endif
- return 0;
-}
-
-int tls_client_key_exchange_post_work(SSL *s)
-{
- unsigned char *pms = NULL;
- size_t pmslen = 0;
-
- pms = s->s3->tmp.pms;
- pmslen = s->s3->tmp.pmslen;
-
-#ifndef OPENSSL_NO_SRP
- /* Check for SRP */
- if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
- if (!srp_generate_client_master_secret(s)) {
- /* SSLfatal() already called */
- goto err;
- }
- return 1;
- }
-#endif
-
- if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
- /* SSLfatal() already called */
- /* ssl_generate_master_secret frees the pms even on error */
- pms = NULL;
- pmslen = 0;
- goto err;
- }
- pms = NULL;
- pmslen = 0;
-
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s)) {
- unsigned char sctpauthkey[64];
- char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
- size_t labellen;
-
- /*
- * Add new shared key for SCTP-Auth, will be ignored if no SCTP
- * used.
- */
- memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
- sizeof(DTLS1_SCTP_AUTH_LABEL));
-
- /* Don't include the terminating zero. */
- labellen = sizeof(labelbuffer) - 1;
- if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
- labellen += 1;
-
- if (SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- labellen, NULL, 0, 0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
- sizeof(sctpauthkey), sctpauthkey);
- }
-#endif
-
- return 1;
- err:
- OPENSSL_clear_free(pms, pmslen);
- s->s3->tmp.pms = NULL;
+#endif
+ return 0;
+}
+
+int tls_client_key_exchange_post_work(SSL *s)
+{
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+
+ pms = s->s3->tmp.pms;
+ pmslen = s->s3->tmp.pmslen;
+
+#ifndef OPENSSL_NO_SRP
+ /* Check for SRP */
+ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if (!srp_generate_client_master_secret(s)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ return 1;
+ }
+#endif
+
+ if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
+ /* SSLfatal() already called */
+ /* ssl_generate_master_secret frees the pms even on error */
+ pms = NULL;
+ pmslen = 0;
+ goto err;
+ }
+ pms = NULL;
+ pmslen = 0;
+
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s)) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+ size_t labellen;
+
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no SCTP
+ * used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ /* Don't include the terminating zero. */
+ labellen = sizeof(labelbuffer) - 1;
+ if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+ labellen += 1;
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ labellen, NULL, 0, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+#endif
+
+ return 1;
+ err:
+ OPENSSL_clear_free(pms, pmslen);
+ s->s3->tmp.pms = NULL;
s->s3->tmp.pmslen = 0;
- return 0;
-}
-
-/*
- * Check a certificate can be used for client authentication. Currently check
- * cert exists, if we have a suitable digest for TLS 1.2 if static DH client
- * certificates can be used and optionally checks suitability for Suite B.
- */
-static int ssl3_check_client_certificate(SSL *s)
-{
- /* If no suitable signature algorithm can't use certificate */
- if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL)
- return 0;
- /*
- * If strict mode check suitability of chain before using it. This also
- * adjusts suite B digest if necessary.
- */
- if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT &&
- !tls1_check_chain(s, NULL, NULL, NULL, -2))
- return 0;
- return 1;
-}
-
-WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
-{
- X509 *x509 = NULL;
- EVP_PKEY *pkey = NULL;
- int i;
-
- if (wst == WORK_MORE_A) {
- /* Let cert callback update client certificates if required */
- if (s->cert->cert_cb) {
- i = s->cert->cert_cb(s, s->cert->cert_cb_arg);
- if (i < 0) {
- s->rwstate = SSL_X509_LOOKUP;
- return WORK_MORE_A;
- }
- if (i == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
- SSL_R_CALLBACK_FAILED);
- return WORK_ERROR;
- }
- s->rwstate = SSL_NOTHING;
- }
- if (ssl3_check_client_certificate(s)) {
- if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
- return WORK_FINISHED_STOP;
- }
- return WORK_FINISHED_CONTINUE;
- }
-
- /* Fall through to WORK_MORE_B */
- wst = WORK_MORE_B;
- }
-
- /* We need to get a client cert */
- if (wst == WORK_MORE_B) {
- /*
- * If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP;
- * return(-1); We then get retied later
- */
- i = ssl_do_client_cert_cb(s, &x509, &pkey);
- if (i < 0) {
- s->rwstate = SSL_X509_LOOKUP;
- return WORK_MORE_B;
- }
- s->rwstate = SSL_NOTHING;
- if ((i == 1) && (pkey != NULL) && (x509 != NULL)) {
- if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey))
- i = 0;
- } else if (i == 1) {
- i = 0;
- SSLerr(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
- SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
- }
-
- X509_free(x509);
- EVP_PKEY_free(pkey);
- if (i && !ssl3_check_client_certificate(s))
- i = 0;
- if (i == 0) {
- if (s->version == SSL3_VERSION) {
- s->s3->tmp.cert_req = 0;
- ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
- return WORK_FINISHED_CONTINUE;
- } else {
- s->s3->tmp.cert_req = 2;
- if (!ssl3_digest_cached_records(s, 0)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- }
- }
-
- if (s->post_handshake_auth == SSL_PHA_REQUESTED)
- return WORK_FINISHED_STOP;
- return WORK_FINISHED_CONTINUE;
- }
-
- /* Shouldn't ever get here */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
-}
-
-int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
-{
- if (SSL_IS_TLS13(s)) {
- if (s->pha_context == NULL) {
- /* no context available, add 0-length context */
- if (!WPACKET_put_bytes_u8(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- } else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!ssl3_output_cert_chain(s, pkt,
- (s->s3->tmp.cert_req == 2) ? NULL
- : s->cert->key)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- if (SSL_IS_TLS13(s)
- && SSL_IS_FIRST_HANDSHAKE(s)
- && (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
- /*
- * This is a fatal error, which leaves enc_write_ctx in an inconsistent
- * state and thus ssl3_send_alert may crash.
- */
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
- SSL_R_CANNOT_CHANGE_CIPHER);
- return 0;
- }
-
- return 1;
-}
-
-int ssl3_check_cert_and_algorithm(SSL *s)
-{
- const SSL_CERT_LOOKUP *clu;
- size_t idx;
- long alg_k, alg_a;
-
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
- /* we don't have a certificate */
- if (!(alg_a & SSL_aCERT))
- return 1;
-
- /* This is the passed certificate */
- clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx);
-
- /* Check certificate is recognised and suitable for cipher */
- if (clu == NULL || (alg_a & clu->amask) == 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
- SSL_R_MISSING_SIGNING_CERT);
- return 0;
- }
-
-#ifndef OPENSSL_NO_EC
- if (clu->amask & SSL_aECDSA) {
- if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
- return 1;
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
- return 0;
- }
-#endif
-#ifndef OPENSSL_NO_RSA
- if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
- SSL_R_MISSING_RSA_ENCRYPTING_CERT);
- return 0;
- }
-#endif
-#ifndef OPENSSL_NO_DH
- if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-#endif
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
-int tls_construct_next_proto(SSL *s, WPACKET *pkt)
-{
- size_t len, padding_len;
- unsigned char *padding = NULL;
-
- len = s->ext.npn_len;
- padding_len = 32 - ((len + 2) % 32);
-
- if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len)
- || !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- memset(padding, 0, padding_len);
-
- return 1;
-}
-#endif
-
-MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt)
-{
- if (PACKET_remaining(pkt) > 0) {
- /* should contain no data */
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
- ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
- return MSG_PROCESS_FINISHED_READING;
- }
-
- /*
- * This is a historical discrepancy (not in the RFC) maintained for
- * compatibility reasons. If a TLS client receives a HelloRequest it will
- * attempt an abbreviated handshake. However if a DTLS client receives a
- * HelloRequest it will do a full handshake. Either behaviour is reasonable
- * but doing one for TLS and another for DTLS is odd.
- */
- if (SSL_IS_DTLS(s))
- SSL_renegotiate(s);
- else
- SSL_renegotiate_abbreviated(s);
-
- return MSG_PROCESS_FINISHED_READING;
-}
-
-static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt)
-{
- PACKET extensions;
- RAW_EXTENSION *rawexts = NULL;
-
- if (!PACKET_as_length_prefixed_2(pkt, &extensions)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!tls_collect_extensions(s, &extensions,
- SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, &rawexts,
- NULL, 1)
- || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- rawexts, NULL, 0, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- OPENSSL_free(rawexts);
- return MSG_PROCESS_CONTINUE_READING;
-
- err:
- OPENSSL_free(rawexts);
- return MSG_PROCESS_ERROR;
-}
-
-int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
-{
- int i = 0;
-#ifndef OPENSSL_NO_ENGINE
- if (s->ctx->client_cert_engine) {
- i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
- SSL_get_client_CA_list(s),
- px509, ppkey, NULL, NULL, NULL);
- if (i != 0)
- return i;
- }
-#endif
- if (s->ctx->client_cert_cb)
- i = s->ctx->client_cert_cb(s, px509, ppkey);
- return i;
-}
-
-int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
-{
- int i;
- size_t totlen = 0, len, maxlen, maxverok = 0;
- int empty_reneg_info_scsv = !s->renegotiate;
-
- /* Set disabled masks for this session */
- if (!ssl_set_client_disabled(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- SSL_R_NO_PROTOCOLS_AVAILABLE);
- return 0;
- }
-
- if (sk == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
-#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
-# if OPENSSL_MAX_TLS1_2_CIPHER_LENGTH < 6
-# error Max cipher length too short
-# endif
- /*
- * Some servers hang if client hello > 256 bytes as hack workaround
- * chop number of supported ciphers to keep it well below this if we
- * use TLS v1.2
- */
- if (TLS1_get_version(s) >= TLS1_2_VERSION)
- maxlen = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
- else
-#endif
- /* Maximum length that can be stored in 2 bytes. Length must be even */
- maxlen = 0xfffe;
-
- if (empty_reneg_info_scsv)
- maxlen -= 2;
- if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV)
- maxlen -= 2;
-
- for (i = 0; i < sk_SSL_CIPHER_num(sk) && totlen < maxlen; i++) {
- const SSL_CIPHER *c;
-
- c = sk_SSL_CIPHER_value(sk, i);
- /* Skip disabled ciphers */
- if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
- continue;
-
- if (!s->method->put_cipher_by_char(c, pkt, &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* Sanity check that the maximum version we offer has ciphers enabled */
- if (!maxverok) {
- if (SSL_IS_DTLS(s)) {
- if (DTLS_VERSION_GE(c->max_dtls, s->s3->tmp.max_ver)
- && DTLS_VERSION_LE(c->min_dtls, s->s3->tmp.max_ver))
- maxverok = 1;
- } else {
- if (c->max_tls >= s->s3->tmp.max_ver
- && c->min_tls <= s->s3->tmp.max_ver)
- maxverok = 1;
- }
- }
-
- totlen += len;
- }
-
- if (totlen == 0 || !maxverok) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
- SSL_R_NO_CIPHERS_AVAILABLE);
-
- if (!maxverok)
- ERR_add_error_data(1, "No ciphers enabled for max supported "
- "SSL/TLS version");
-
- return 0;
- }
-
- if (totlen != 0) {
- if (empty_reneg_info_scsv) {
- static SSL_CIPHER scsv = {
- 0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) {
- static SSL_CIPHER scsv = {
- 0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- }
-
- return 1;
-}
-
-int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt)
-{
- if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
- && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
-
- s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
- return 1;
-}
+ return 0;
+}
+
+/*
+ * Check a certificate can be used for client authentication. Currently check
+ * cert exists, if we have a suitable digest for TLS 1.2 if static DH client
+ * certificates can be used and optionally checks suitability for Suite B.
+ */
+static int ssl3_check_client_certificate(SSL *s)
+{
+ /* If no suitable signature algorithm can't use certificate */
+ if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL)
+ return 0;
+ /*
+ * If strict mode check suitability of chain before using it. This also
+ * adjusts suite B digest if necessary.
+ */
+ if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT &&
+ !tls1_check_chain(s, NULL, NULL, NULL, -2))
+ return 0;
+ return 1;
+}
+
+WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
+{
+ X509 *x509 = NULL;
+ EVP_PKEY *pkey = NULL;
+ int i;
+
+ if (wst == WORK_MORE_A) {
+ /* Let cert callback update client certificates if required */
+ if (s->cert->cert_cb) {
+ i = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (i < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ return WORK_MORE_A;
+ }
+ if (i == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
+ SSL_R_CALLBACK_FAILED);
+ return WORK_ERROR;
+ }
+ s->rwstate = SSL_NOTHING;
+ }
+ if (ssl3_check_client_certificate(s)) {
+ if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
+ return WORK_FINISHED_STOP;
+ }
+ return WORK_FINISHED_CONTINUE;
+ }
+
+ /* Fall through to WORK_MORE_B */
+ wst = WORK_MORE_B;
+ }
+
+ /* We need to get a client cert */
+ if (wst == WORK_MORE_B) {
+ /*
+ * If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP;
+ * return(-1); We then get retied later
+ */
+ i = ssl_do_client_cert_cb(s, &x509, &pkey);
+ if (i < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ return WORK_MORE_B;
+ }
+ s->rwstate = SSL_NOTHING;
+ if ((i == 1) && (pkey != NULL) && (x509 != NULL)) {
+ if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey))
+ i = 0;
+ } else if (i == 1) {
+ i = 0;
+ SSLerr(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
+ SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+ }
+
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+ if (i && !ssl3_check_client_certificate(s))
+ i = 0;
+ if (i == 0) {
+ if (s->version == SSL3_VERSION) {
+ s->s3->tmp.cert_req = 0;
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
+ return WORK_FINISHED_CONTINUE;
+ } else {
+ s->s3->tmp.cert_req = 2;
+ if (!ssl3_digest_cached_records(s, 0)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ }
+ }
+
+ if (s->post_handshake_auth == SSL_PHA_REQUESTED)
+ return WORK_FINISHED_STOP;
+ return WORK_FINISHED_CONTINUE;
+ }
+
+ /* Shouldn't ever get here */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+}
+
+int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
+{
+ if (SSL_IS_TLS13(s)) {
+ if (s->pha_context == NULL) {
+ /* no context available, add 0-length context */
+ if (!WPACKET_put_bytes_u8(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (!ssl3_output_cert_chain(s, pkt,
+ (s->s3->tmp.cert_req == 2) ? NULL
+ : s->cert->key)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ if (SSL_IS_TLS13(s)
+ && SSL_IS_FIRST_HANDSHAKE(s)
+ && (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
+ /*
+ * This is a fatal error, which leaves enc_write_ctx in an inconsistent
+ * state and thus ssl3_send_alert may crash.
+ */
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
+ SSL_R_CANNOT_CHANGE_CIPHER);
+ return 0;
+ }
+
+ return 1;
+}
+
+int ssl3_check_cert_and_algorithm(SSL *s)
+{
+ const SSL_CERT_LOOKUP *clu;
+ size_t idx;
+ long alg_k, alg_a;
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ /* we don't have a certificate */
+ if (!(alg_a & SSL_aCERT))
+ return 1;
+
+ /* This is the passed certificate */
+ clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx);
+
+ /* Check certificate is recognised and suitable for cipher */
+ if (clu == NULL || (alg_a & clu->amask) == 0) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+ SSL_R_MISSING_SIGNING_CERT);
+ return 0;
+ }
+
+#ifndef OPENSSL_NO_EC
+ if (clu->amask & SSL_aECDSA) {
+ if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
+ return 1;
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
+ return 0;
+ }
+#endif
+#ifndef OPENSSL_NO_RSA
+ if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+ SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+ return 0;
+ }
+#endif
+#ifndef OPENSSL_NO_DH
+ if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+int tls_construct_next_proto(SSL *s, WPACKET *pkt)
+{
+ size_t len, padding_len;
+ unsigned char *padding = NULL;
+
+ len = s->ext.npn_len;
+ padding_len = 32 - ((len + 2) % 32);
+
+ if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len)
+ || !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ memset(padding, 0, padding_len);
+
+ return 1;
+}
+#endif
+
+MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt)
+{
+ if (PACKET_remaining(pkt) > 0) {
+ /* should contain no data */
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
+ return MSG_PROCESS_FINISHED_READING;
+ }
+
+ /*
+ * This is a historical discrepancy (not in the RFC) maintained for
+ * compatibility reasons. If a TLS client receives a HelloRequest it will
+ * attempt an abbreviated handshake. However if a DTLS client receives a
+ * HelloRequest it will do a full handshake. Either behaviour is reasonable
+ * but doing one for TLS and another for DTLS is odd.
+ */
+ if (SSL_IS_DTLS(s))
+ SSL_renegotiate(s);
+ else
+ SSL_renegotiate_abbreviated(s);
+
+ return MSG_PROCESS_FINISHED_READING;
+}
+
+static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt)
+{
+ PACKET extensions;
+ RAW_EXTENSION *rawexts = NULL;
+
+ if (!PACKET_as_length_prefixed_2(pkt, &extensions)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!tls_collect_extensions(s, &extensions,
+ SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, &rawexts,
+ NULL, 1)
+ || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
+ rawexts, NULL, 0, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ OPENSSL_free(rawexts);
+ return MSG_PROCESS_CONTINUE_READING;
+
+ err:
+ OPENSSL_free(rawexts);
+ return MSG_PROCESS_ERROR;
+}
+
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
+{
+ int i = 0;
+#ifndef OPENSSL_NO_ENGINE
+ if (s->ctx->client_cert_engine) {
+ i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
+ SSL_get_client_CA_list(s),
+ px509, ppkey, NULL, NULL, NULL);
+ if (i != 0)
+ return i;
+ }
+#endif
+ if (s->ctx->client_cert_cb)
+ i = s->ctx->client_cert_cb(s, px509, ppkey);
+ return i;
+}
+
+int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
+{
+ int i;
+ size_t totlen = 0, len, maxlen, maxverok = 0;
+ int empty_reneg_info_scsv = !s->renegotiate;
+
+ /* Set disabled masks for this session */
+ if (!ssl_set_client_disabled(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
+ SSL_R_NO_PROTOCOLS_AVAILABLE);
+ return 0;
+ }
+
+ if (sk == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
+# if OPENSSL_MAX_TLS1_2_CIPHER_LENGTH < 6
+# error Max cipher length too short
+# endif
+ /*
+ * Some servers hang if client hello > 256 bytes as hack workaround
+ * chop number of supported ciphers to keep it well below this if we
+ * use TLS v1.2
+ */
+ if (TLS1_get_version(s) >= TLS1_2_VERSION)
+ maxlen = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
+ else
+#endif
+ /* Maximum length that can be stored in 2 bytes. Length must be even */
+ maxlen = 0xfffe;
+
+ if (empty_reneg_info_scsv)
+ maxlen -= 2;
+ if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV)
+ maxlen -= 2;
+
+ for (i = 0; i < sk_SSL_CIPHER_num(sk) && totlen < maxlen; i++) {
+ const SSL_CIPHER *c;
+
+ c = sk_SSL_CIPHER_value(sk, i);
+ /* Skip disabled ciphers */
+ if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
+ continue;
+
+ if (!s->method->put_cipher_by_char(c, pkt, &len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Sanity check that the maximum version we offer has ciphers enabled */
+ if (!maxverok) {
+ if (SSL_IS_DTLS(s)) {
+ if (DTLS_VERSION_GE(c->max_dtls, s->s3->tmp.max_ver)
+ && DTLS_VERSION_LE(c->min_dtls, s->s3->tmp.max_ver))
+ maxverok = 1;
+ } else {
+ if (c->max_tls >= s->s3->tmp.max_ver
+ && c->min_tls <= s->s3->tmp.max_ver)
+ maxverok = 1;
+ }
+ }
+
+ totlen += len;
+ }
+
+ if (totlen == 0 || !maxverok) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
+ SSL_R_NO_CIPHERS_AVAILABLE);
+
+ if (!maxverok)
+ ERR_add_error_data(1, "No ciphers enabled for max supported "
+ "SSL/TLS version");
+
+ return 0;
+ }
+
+ if (totlen != 0) {
+ if (empty_reneg_info_scsv) {
+ static SSL_CIPHER scsv = {
+ 0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) {
+ static SSL_CIPHER scsv = {
+ 0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt)
+{
+ if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
+ && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ return 1;
+}
diff --git a/contrib/libs/openssl/ssl/statem/statem_dtls.c b/contrib/libs/openssl/ssl/statem/statem_dtls.c
index 8e3fb686ee..6e35f2109c 100644
--- a/contrib/libs/openssl/ssl/statem/statem_dtls.c
+++ b/contrib/libs/openssl/ssl/statem/statem_dtls.c
@@ -1,1281 +1,1281 @@
-/*
- * Copyright 2005-2018 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 <limits.h>
-#include <string.h>
-#include <stdio.h>
+/*
+ * Copyright 2005-2018 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 <limits.h>
+#include <string.h>
+#include <stdio.h>
#include "../ssl_local.h"
#include "statem_local.h"
-#include "internal/cryptlib.h"
-#include <openssl/buffer.h>
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-
-#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
-
-#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
- if ((end) - (start) <= 8) { \
- long ii; \
- for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
- } else { \
- long ii; \
- bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
- for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
- bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
- } }
-
-#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
- long ii; \
- is_complete = 1; \
- if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
- if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
- if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
-
-static unsigned char bitmask_start_values[] =
- { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
-static unsigned char bitmask_end_values[] =
- { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
-
-static void dtls1_fix_message_header(SSL *s, size_t frag_off,
- size_t frag_len);
-static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
-static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
- size_t len,
- unsigned short seq_num,
- size_t frag_off,
- size_t frag_len);
-static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len);
-
-static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly)
-{
- hm_fragment *frag = NULL;
- unsigned char *buf = NULL;
- unsigned char *bitmask = NULL;
-
- if ((frag = OPENSSL_malloc(sizeof(*frag))) == NULL) {
- SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
-
- if (frag_len) {
- if ((buf = OPENSSL_malloc(frag_len)) == NULL) {
- SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(frag);
- return NULL;
- }
- }
-
- /* zero length fragment gets zero frag->fragment */
- frag->fragment = buf;
-
- /* Initialize reassembly bitmask if necessary */
- if (reassembly) {
- bitmask = OPENSSL_zalloc(RSMBLY_BITMASK_SIZE(frag_len));
- if (bitmask == NULL) {
- SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(buf);
- OPENSSL_free(frag);
- return NULL;
- }
- }
-
- frag->reassembly = bitmask;
-
- return frag;
-}
-
-void dtls1_hm_fragment_free(hm_fragment *frag)
-{
- if (!frag)
- return;
- if (frag->msg_header.is_ccs) {
- EVP_CIPHER_CTX_free(frag->msg_header.
- saved_retransmit_state.enc_write_ctx);
- EVP_MD_CTX_free(frag->msg_header.saved_retransmit_state.write_hash);
- }
- OPENSSL_free(frag->fragment);
- OPENSSL_free(frag->reassembly);
- OPENSSL_free(frag);
-}
-
-/*
- * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
- * SSL3_RT_CHANGE_CIPHER_SPEC)
- */
-int dtls1_do_write(SSL *s, int type)
-{
- int ret;
- size_t written;
- size_t curr_mtu;
- int retry = 1;
- size_t len, frag_off, mac_size, blocksize, used_len;
-
- if (!dtls1_query_mtu(s))
- return -1;
-
- if (s->d1->mtu < dtls1_min_mtu(s))
- /* should have something reasonable now */
- return -1;
-
- if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE) {
- if (!ossl_assert(s->init_num ==
- s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH))
- return -1;
- }
-
- if (s->write_hash) {
- if (s->enc_write_ctx
- && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
- EVP_CIPH_FLAG_AEAD_CIPHER) != 0)
- mac_size = 0;
- else
- mac_size = EVP_MD_CTX_size(s->write_hash);
- } else
- mac_size = 0;
-
- if (s->enc_write_ctx &&
- (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
- blocksize = 2 * EVP_CIPHER_CTX_block_size(s->enc_write_ctx);
- else
- blocksize = 0;
-
- frag_off = 0;
- s->rwstate = SSL_NOTHING;
-
- /* s->init_num shouldn't ever be < 0...but just in case */
- while (s->init_num > 0) {
- if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) {
- /* We must be writing a fragment other than the first one */
-
- if (frag_off > 0) {
- /* This is the first attempt at writing out this fragment */
-
- if (s->init_off <= DTLS1_HM_HEADER_LENGTH) {
- /*
- * Each fragment that was already sent must at least have
- * contained the message header plus one other byte.
- * Therefore |init_off| must have progressed by at least
- * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went
- * wrong.
- */
- return -1;
- }
-
- /*
- * Adjust |init_off| and |init_num| to allow room for a new
- * message header for this fragment.
- */
- s->init_off -= DTLS1_HM_HEADER_LENGTH;
- s->init_num += DTLS1_HM_HEADER_LENGTH;
- } else {
- /*
- * We must have been called again after a retry so use the
- * fragment offset from our last attempt. We do not need
- * to adjust |init_off| and |init_num| as above, because
- * that should already have been done before the retry.
- */
- frag_off = s->d1->w_msg_hdr.frag_off;
- }
- }
-
- used_len = BIO_wpending(s->wbio) + DTLS1_RT_HEADER_LENGTH
- + mac_size + blocksize;
- if (s->d1->mtu > used_len)
- curr_mtu = s->d1->mtu - used_len;
- else
- curr_mtu = 0;
-
- if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
- /*
- * grr.. we could get an error if MTU picked was wrong
- */
- ret = BIO_flush(s->wbio);
- if (ret <= 0) {
- s->rwstate = SSL_WRITING;
- return ret;
- }
- used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
- if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
- curr_mtu = s->d1->mtu - used_len;
- } else {
- /* Shouldn't happen */
- return -1;
- }
- }
-
- /*
- * We just checked that s->init_num > 0 so this cast should be safe
- */
- if (((unsigned int)s->init_num) > curr_mtu)
- len = curr_mtu;
- else
- len = s->init_num;
-
- if (len > s->max_send_fragment)
- len = s->max_send_fragment;
-
- /*
- * XDTLS: this function is too long. split out the CCS part
- */
- if (type == SSL3_RT_HANDSHAKE) {
- if (len < DTLS1_HM_HEADER_LENGTH) {
- /*
- * len is so small that we really can't do anything sensible
- * so fail
- */
- return -1;
- }
- dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH);
-
- dtls1_write_message_header(s,
- (unsigned char *)&s->init_buf->
- data[s->init_off]);
- }
-
- ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len,
- &written);
- if (ret < 0) {
- /*
- * might need to update MTU here, but we don't know which
- * previous packet caused the failure -- so can't really
- * retransmit anything. continue as if everything is fine and
- * wait for an alert to handle the retransmit
- */
- if (retry && BIO_ctrl(SSL_get_wbio(s),
- BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) {
- if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
- if (!dtls1_query_mtu(s))
- return -1;
- /* Have one more go */
- retry = 0;
- } else
- return -1;
- } else {
- return -1;
- }
- } else {
-
- /*
- * bad if this assert fails, only part of the handshake message
- * got sent. but why would this happen?
- */
- if (!ossl_assert(len == written))
- return -1;
-
- if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) {
- /*
- * should not be done for 'Hello Request's, but in that case
- * we'll ignore the result anyway
- */
- unsigned char *p =
- (unsigned char *)&s->init_buf->data[s->init_off];
- const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
- size_t xlen;
-
- if (frag_off == 0 && s->version != DTLS1_BAD_VER) {
- /*
- * reconstruct message header is if it is being sent in
- * single fragment
- */
- *p++ = msg_hdr->type;
- l2n3(msg_hdr->msg_len, p);
- s2n(msg_hdr->seq, p);
- l2n3(0, p);
- l2n3(msg_hdr->msg_len, p);
- p -= DTLS1_HM_HEADER_LENGTH;
- xlen = written;
- } else {
- p += DTLS1_HM_HEADER_LENGTH;
- xlen = written - DTLS1_HM_HEADER_LENGTH;
- }
-
- if (!ssl3_finish_mac(s, p, xlen))
- return -1;
- }
-
- if (written == s->init_num) {
- if (s->msg_callback)
- s->msg_callback(1, s->version, type, s->init_buf->data,
- (size_t)(s->init_off + s->init_num), s,
- s->msg_callback_arg);
-
- s->init_off = 0; /* done writing this message */
- s->init_num = 0;
-
- return 1;
- }
- s->init_off += written;
- s->init_num -= written;
- written -= DTLS1_HM_HEADER_LENGTH;
- frag_off += written;
-
- /*
- * We save the fragment offset for the next fragment so we have it
- * available in case of an IO retry. We don't know the length of the
- * next fragment yet so just set that to 0 for now. It will be
- * updated again later.
- */
- dtls1_fix_message_header(s, frag_off, 0);
- }
- }
- return 0;
-}
-
-int dtls_get_message(SSL *s, int *mt, size_t *len)
-{
- struct hm_header_st *msg_hdr;
- unsigned char *p;
- size_t msg_len;
- size_t tmplen;
- int errtype;
-
- msg_hdr = &s->d1->r_msg_hdr;
- memset(msg_hdr, 0, sizeof(*msg_hdr));
-
- again:
- if (!dtls_get_reassembled_message(s, &errtype, &tmplen)) {
- if (errtype == DTLS1_HM_BAD_FRAGMENT
- || errtype == DTLS1_HM_FRAGMENT_RETRY) {
- /* bad fragment received */
- goto again;
- }
- return 0;
- }
-
- *mt = s->s3->tmp.message_type;
-
- p = (unsigned char *)s->init_buf->data;
- *len = s->init_num;
-
- if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- if (s->msg_callback) {
- s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
- p, 1, s, s->msg_callback_arg);
- }
- /*
- * This isn't a real handshake message so skip the processing below.
- */
- return 1;
- }
-
- msg_len = msg_hdr->msg_len;
-
- /* reconstruct message header */
- *(p++) = msg_hdr->type;
- l2n3(msg_len, p);
- s2n(msg_hdr->seq, p);
- l2n3(0, p);
- l2n3(msg_len, p);
- if (s->version != DTLS1_BAD_VER) {
- p -= DTLS1_HM_HEADER_LENGTH;
- msg_len += DTLS1_HM_HEADER_LENGTH;
- }
-
- /*
- * If receiving Finished, record MAC of prior handshake messages for
- * Finished verification.
- */
- if (*mt == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- if (!ssl3_finish_mac(s, p, msg_len))
- return 0;
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- p, msg_len, s, s->msg_callback_arg);
-
- memset(msg_hdr, 0, sizeof(*msg_hdr));
-
- s->d1->handshake_read_seq++;
-
- s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
-
- return 1;
-}
-
-/*
- * dtls1_max_handshake_message_len returns the maximum number of bytes
- * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
- * may be greater if the maximum certificate list size requires it.
- */
-static size_t dtls1_max_handshake_message_len(const SSL *s)
-{
- size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
- if (max_len < s->max_cert_list)
- return s->max_cert_list;
- return max_len;
-}
-
-static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
-{
- size_t frag_off, frag_len, msg_len;
-
- msg_len = msg_hdr->msg_len;
- frag_off = msg_hdr->frag_off;
- frag_len = msg_hdr->frag_len;
-
- /* sanity checking */
- if ((frag_off + frag_len) > msg_len
- || msg_len > dtls1_max_handshake_message_len(s)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
- SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return 0;
- }
-
- if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
- /*
- * msg_len is limited to 2^24, but is effectively checked against
- * dtls_max_handshake_message_len(s) above
- */
- if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
- ERR_R_BUF_LIB);
- return 0;
- }
-
- s->s3->tmp.message_size = msg_len;
- s->d1->r_msg_hdr.msg_len = msg_len;
- s->s3->tmp.message_type = msg_hdr->type;
- s->d1->r_msg_hdr.type = msg_hdr->type;
- s->d1->r_msg_hdr.seq = msg_hdr->seq;
- } else if (msg_len != s->d1->r_msg_hdr.msg_len) {
- /*
- * They must be playing with us! BTW, failure to enforce upper limit
- * would open possibility for buffer overrun.
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
- SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Returns 1 if there is a buffered fragment available, 0 if not, or -1 on a
- * fatal error.
- */
-static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
-{
- /*-
- * (0) check whether the desired fragment is available
- * if so:
- * (1) copy over the fragment to s->init_buf->data[]
- * (2) update s->init_num
- */
- pitem *item;
- hm_fragment *frag;
- int ret;
-
- do {
- item = pqueue_peek(s->d1->buffered_messages);
- if (item == NULL)
- return 0;
-
- frag = (hm_fragment *)item->data;
-
- if (frag->msg_header.seq < s->d1->handshake_read_seq) {
- /* This is a stale message that has been buffered so clear it */
- pqueue_pop(s->d1->buffered_messages);
- dtls1_hm_fragment_free(frag);
- pitem_free(item);
- item = NULL;
- frag = NULL;
- }
- } while (item == NULL);
-
- /* Don't return if reassembly still in progress */
- if (frag->reassembly != NULL)
- return 0;
-
- if (s->d1->handshake_read_seq == frag->msg_header.seq) {
- size_t frag_len = frag->msg_header.frag_len;
- pqueue_pop(s->d1->buffered_messages);
-
- /* Calls SSLfatal() as required */
- ret = dtls1_preprocess_fragment(s, &frag->msg_header);
-
- if (ret && frag->msg_header.frag_len > 0) {
- unsigned char *p =
- (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
- memcpy(&p[frag->msg_header.frag_off], frag->fragment,
- frag->msg_header.frag_len);
- }
-
- dtls1_hm_fragment_free(frag);
- pitem_free(item);
-
- if (ret) {
- *len = frag_len;
- return 1;
- }
-
- /* Fatal error */
- s->init_num = 0;
- return -1;
- } else {
- return 0;
- }
-}
-
-static int
-dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr)
-{
- hm_fragment *frag = NULL;
- pitem *item = NULL;
- int i = -1, is_complete;
- unsigned char seq64be[8];
- size_t frag_len = msg_hdr->frag_len;
- size_t readbytes;
-
- if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
- msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
- goto err;
-
- if (frag_len == 0) {
- return DTLS1_HM_FRAGMENT_RETRY;
- }
-
- /* Try to find item in queue */
- memset(seq64be, 0, sizeof(seq64be));
- seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
- seq64be[7] = (unsigned char)msg_hdr->seq;
- item = pqueue_find(s->d1->buffered_messages, seq64be);
-
- if (item == NULL) {
- frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
- if (frag == NULL)
- goto err;
- memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
- frag->msg_header.frag_len = frag->msg_header.msg_len;
- frag->msg_header.frag_off = 0;
- } else {
- frag = (hm_fragment *)item->data;
- if (frag->msg_header.msg_len != msg_hdr->msg_len) {
- item = NULL;
- frag = NULL;
- goto err;
- }
- }
-
- /*
- * If message is already reassembled, this must be a retransmit and can
- * be dropped. In this case item != NULL and so frag does not need to be
- * freed.
- */
- if (frag->reassembly == NULL) {
- unsigned char devnull[256];
-
- while (frag_len) {
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
- devnull,
- frag_len >
- sizeof(devnull) ? sizeof(devnull) :
- frag_len, 0, &readbytes);
- if (i <= 0)
- goto err;
- frag_len -= readbytes;
- }
- return DTLS1_HM_FRAGMENT_RETRY;
- }
-
- /* read the body of the fragment (header has already been read */
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
- frag->fragment + msg_hdr->frag_off,
- frag_len, 0, &readbytes);
- if (i <= 0 || readbytes != frag_len)
- i = -1;
- if (i <= 0)
- goto err;
-
- RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
- (long)(msg_hdr->frag_off + frag_len));
-
- if (!ossl_assert(msg_hdr->msg_len > 0))
- goto err;
- RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
- is_complete);
-
- if (is_complete) {
- OPENSSL_free(frag->reassembly);
- frag->reassembly = NULL;
- }
-
- if (item == NULL) {
- item = pitem_new(seq64be, frag);
- if (item == NULL) {
- i = -1;
- goto err;
- }
-
- item = pqueue_insert(s->d1->buffered_messages, item);
- /*
- * pqueue_insert fails iff a duplicate item is inserted. However,
- * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
- * would have returned it and control would never have reached this
- * branch.
- */
- if (!ossl_assert(item != NULL))
- goto err;
- }
-
- return DTLS1_HM_FRAGMENT_RETRY;
-
- err:
- if (item == NULL)
- dtls1_hm_fragment_free(frag);
- return -1;
-}
-
-static int
-dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr)
-{
- int i = -1;
- hm_fragment *frag = NULL;
- pitem *item = NULL;
- unsigned char seq64be[8];
- size_t frag_len = msg_hdr->frag_len;
- size_t readbytes;
-
- if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
- goto err;
-
- /* Try to find item in queue, to prevent duplicate entries */
- memset(seq64be, 0, sizeof(seq64be));
- seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
- seq64be[7] = (unsigned char)msg_hdr->seq;
- item = pqueue_find(s->d1->buffered_messages, seq64be);
-
- /*
- * If we already have an entry and this one is a fragment, don't discard
- * it and rather try to reassemble it.
- */
- if (item != NULL && frag_len != msg_hdr->msg_len)
- item = NULL;
-
- /*
- * Discard the message if sequence number was already there, is too far
- * in the future, already in the queue or if we received a FINISHED
- * before the SERVER_HELLO, which then must be a stale retransmit.
- */
- if (msg_hdr->seq <= s->d1->handshake_read_seq ||
- msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
- (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) {
- unsigned char devnull[256];
-
- while (frag_len) {
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
- devnull,
- frag_len >
- sizeof(devnull) ? sizeof(devnull) :
- frag_len, 0, &readbytes);
- if (i <= 0)
- goto err;
- frag_len -= readbytes;
- }
- } else {
- if (frag_len != msg_hdr->msg_len) {
- return dtls1_reassemble_fragment(s, msg_hdr);
- }
-
- if (frag_len > dtls1_max_handshake_message_len(s))
- goto err;
-
- frag = dtls1_hm_fragment_new(frag_len, 0);
- if (frag == NULL)
- goto err;
-
- memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
-
- if (frag_len) {
- /*
- * read the body of the fragment (header has already been read
- */
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
- frag->fragment, frag_len, 0,
- &readbytes);
- if (i<=0 || readbytes != frag_len)
- i = -1;
- if (i <= 0)
- goto err;
- }
-
- item = pitem_new(seq64be, frag);
- if (item == NULL)
- goto err;
-
- item = pqueue_insert(s->d1->buffered_messages, item);
- /*
- * pqueue_insert fails iff a duplicate item is inserted. However,
- * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
- * would have returned it. Then, either |frag_len| !=
- * |msg_hdr->msg_len| in which case |item| is set to NULL and it will
- * have been processed with |dtls1_reassemble_fragment|, above, or
- * the record will have been discarded.
- */
- if (!ossl_assert(item != NULL))
- goto err;
- }
-
- return DTLS1_HM_FRAGMENT_RETRY;
-
- err:
- if (item == NULL)
- dtls1_hm_fragment_free(frag);
- return 0;
-}
-
-static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
-{
- unsigned char wire[DTLS1_HM_HEADER_LENGTH];
- size_t mlen, frag_off, frag_len;
- int i, ret, recvd_type;
- struct hm_header_st msg_hdr;
- size_t readbytes;
-
- *errtype = 0;
-
- redo:
- /* see if we have the required fragment already */
- ret = dtls1_retrieve_buffered_fragment(s, &frag_len);
- if (ret < 0) {
- /* SSLfatal() already called */
- return 0;
- }
- if (ret > 0) {
- s->init_num = frag_len;
- *len = frag_len;
- return 1;
- }
-
- /* read handshake message header */
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, wire,
- DTLS1_HM_HEADER_LENGTH, 0, &readbytes);
- if (i <= 0) { /* nbio, or an error */
- s->rwstate = SSL_READING;
- *len = 0;
- return 0;
- }
- if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
- if (wire[0] != SSL3_MT_CCS) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
- SSL_R_BAD_CHANGE_CIPHER_SPEC);
- goto f_err;
- }
-
- memcpy(s->init_buf->data, wire, readbytes);
- s->init_num = readbytes - 1;
- s->init_msg = s->init_buf->data + 1;
- s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
- s->s3->tmp.message_size = readbytes - 1;
- *len = readbytes - 1;
- return 1;
- }
-
- /* Handshake fails if message header is incomplete */
- if (readbytes != DTLS1_HM_HEADER_LENGTH) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
-
- /* parse the message fragment header */
- dtls1_get_message_header(wire, &msg_hdr);
-
- mlen = msg_hdr.msg_len;
- frag_off = msg_hdr.frag_off;
- frag_len = msg_hdr.frag_len;
-
- /*
- * We must have at least frag_len bytes left in the record to be read.
- * Fragments must not span records.
- */
- if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
- goto f_err;
- }
-
- /*
- * if this is a future (or stale) message it gets buffered
- * (or dropped)--no further processing at this time
- * While listening, we accept seq 1 (ClientHello with cookie)
- * although we're still expecting seq 0 (ClientHello)
- */
- if (msg_hdr.seq != s->d1->handshake_read_seq) {
- *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr);
- return 0;
- }
-
- if (frag_len && frag_len < mlen) {
- *errtype = dtls1_reassemble_fragment(s, &msg_hdr);
- return 0;
- }
-
- if (!s->server
- && s->d1->r_msg_hdr.frag_off == 0
- && s->statem.hand_state != TLS_ST_OK
- && wire[0] == SSL3_MT_HELLO_REQUEST) {
- /*
- * The server may always send 'Hello Request' messages -- we are
- * doing a handshake anyway now, so ignore them if their format is
- * correct. Does not count for 'Finished' MAC.
- */
- if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) {
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- wire, DTLS1_HM_HEADER_LENGTH, s,
- s->msg_callback_arg);
-
- s->init_num = 0;
- goto redo;
- } else { /* Incorrectly formatted Hello request */
-
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
- SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
- }
-
- if (!dtls1_preprocess_fragment(s, &msg_hdr)) {
- /* SSLfatal() already called */
- goto f_err;
- }
-
- if (frag_len > 0) {
- unsigned char *p =
- (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
-
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
- &p[frag_off], frag_len, 0, &readbytes);
-
- /*
- * This shouldn't ever fail due to NBIO because we already checked
- * that we have enough data in the record
- */
- if (i <= 0) {
- s->rwstate = SSL_READING;
- *len = 0;
- return 0;
- }
- } else {
- readbytes = 0;
- }
-
- /*
- * XDTLS: an incorrectly formatted fragment should cause the handshake
- * to fail
- */
- if (readbytes != frag_len) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
- goto f_err;
- }
-
- /*
- * Note that s->init_num is *not* used as current offset in
- * s->init_buf->data, but as a counter summing up fragments' lengths: as
- * soon as they sum up to handshake packet length, we assume we have got
- * all the fragments.
- */
- *len = s->init_num = frag_len;
- return 1;
-
- f_err:
- s->init_num = 0;
- *len = 0;
- return 0;
-}
-
-/*-
- * for these 2 messages, we need to
- * ssl->enc_read_ctx re-init
- * ssl->rlayer.read_sequence zero
- * ssl->s3->read_mac_secret re-init
- * ssl->session->read_sym_enc assign
- * ssl->session->read_compression assign
- * ssl->session->read_hash assign
- */
-int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
-{
- if (s->version == DTLS1_BAD_VER) {
- s->d1->next_handshake_write_seq++;
-
- if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_SCTP
-/*
- * Wait for a dry event. Should only be called at a point in the handshake
- * where we are not expecting any data from the peer except an alert.
- */
-WORK_STATE dtls_wait_for_dry(SSL *s)
-{
- int ret, errtype;
- size_t len;
-
- /* read app data until dry event */
- ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
- if (ret < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS_WAIT_FOR_DRY,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
- }
-
- if (ret == 0) {
- /*
- * We're not expecting any more messages from the peer at this point -
- * but we could get an alert. If an alert is waiting then we will never
- * return successfully. Therefore we attempt to read a message. This
- * should never succeed but will process any waiting alerts.
- */
- if (dtls_get_reassembled_message(s, &errtype, &len)) {
- /* The call succeeded! This should never happen */
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS_WAIT_FOR_DRY,
- SSL_R_UNEXPECTED_MESSAGE);
- return WORK_ERROR;
- }
-
- s->s3->in_read_app_data = 2;
- s->rwstate = SSL_READING;
- BIO_clear_retry_flags(SSL_get_rbio(s));
- BIO_set_retry_read(SSL_get_rbio(s));
- return WORK_MORE_A;
- }
- return WORK_FINISHED_CONTINUE;
-}
-#endif
-
-int dtls1_read_failed(SSL *s, int code)
-{
- if (code > 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!dtls1_is_timer_expired(s) || ossl_statem_in_error(s)) {
- /*
- * not a timeout, none of our business, let higher layers handle
- * this. in fact it's probably an error
- */
- return code;
- }
- /* done, no need to send a retransmit */
- if (!SSL_in_init(s))
- {
- BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
- return code;
- }
-
- return dtls1_handle_timeout(s);
-}
-
-int dtls1_get_queue_priority(unsigned short seq, int is_ccs)
-{
- /*
- * The index of the retransmission queue actually is the message sequence
- * number, since the queue only contains messages of a single handshake.
- * However, the ChangeCipherSpec has no message sequence number and so
- * using only the sequence will result in the CCS and Finished having the
- * same index. To prevent this, the sequence number is multiplied by 2.
- * In case of a CCS 1 is subtracted. This does not only differ CSS and
- * Finished, it also maintains the order of the index (important for
- * priority queues) and fits in the unsigned short variable.
- */
- return seq * 2 - is_ccs;
-}
-
-int dtls1_retransmit_buffered_messages(SSL *s)
-{
- pqueue *sent = s->d1->sent_messages;
- piterator iter;
- pitem *item;
- hm_fragment *frag;
- int found = 0;
-
- iter = pqueue_iterator(sent);
-
- for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) {
- frag = (hm_fragment *)item->data;
- if (dtls1_retransmit_message(s, (unsigned short)
- dtls1_get_queue_priority
- (frag->msg_header.seq,
- frag->msg_header.is_ccs), &found) <= 0)
- return -1;
- }
-
- return 1;
-}
-
-int dtls1_buffer_message(SSL *s, int is_ccs)
-{
- pitem *item;
- hm_fragment *frag;
- unsigned char seq64be[8];
-
- /*
- * this function is called immediately after a message has been
- * serialized
- */
- if (!ossl_assert(s->init_off == 0))
- return 0;
-
- frag = dtls1_hm_fragment_new(s->init_num, 0);
- if (frag == NULL)
- return 0;
-
- memcpy(frag->fragment, s->init_buf->data, s->init_num);
-
- if (is_ccs) {
- /* For DTLS1_BAD_VER the header length is non-standard */
- if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
- ((s->version ==
- DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH)
- == (unsigned int)s->init_num))
- return 0;
- } else {
- if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
- DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num))
- return 0;
- }
-
- frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
- frag->msg_header.seq = s->d1->w_msg_hdr.seq;
- frag->msg_header.type = s->d1->w_msg_hdr.type;
- frag->msg_header.frag_off = 0;
- frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
- frag->msg_header.is_ccs = is_ccs;
-
- /* save current state */
- frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
- frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
- frag->msg_header.saved_retransmit_state.compress = s->compress;
- frag->msg_header.saved_retransmit_state.session = s->session;
- frag->msg_header.saved_retransmit_state.epoch =
- DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
-
- memset(seq64be, 0, sizeof(seq64be));
- seq64be[6] =
- (unsigned
- char)(dtls1_get_queue_priority(frag->msg_header.seq,
- frag->msg_header.is_ccs) >> 8);
- seq64be[7] =
- (unsigned
- char)(dtls1_get_queue_priority(frag->msg_header.seq,
- frag->msg_header.is_ccs));
-
- item = pitem_new(seq64be, frag);
- if (item == NULL) {
- dtls1_hm_fragment_free(frag);
- return 0;
- }
-
- pqueue_insert(s->d1->sent_messages, item);
- return 1;
-}
-
-int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
-{
- int ret;
- /* XDTLS: for now assuming that read/writes are blocking */
- pitem *item;
- hm_fragment *frag;
- unsigned long header_length;
- unsigned char seq64be[8];
- struct dtls1_retransmit_state saved_state;
-
- /* XDTLS: the requested message ought to be found, otherwise error */
- memset(seq64be, 0, sizeof(seq64be));
- seq64be[6] = (unsigned char)(seq >> 8);
- seq64be[7] = (unsigned char)seq;
-
- item = pqueue_find(s->d1->sent_messages, seq64be);
- if (item == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_RETRANSMIT_MESSAGE,
- ERR_R_INTERNAL_ERROR);
- *found = 0;
- return 0;
- }
-
- *found = 1;
- frag = (hm_fragment *)item->data;
-
- if (frag->msg_header.is_ccs)
- header_length = DTLS1_CCS_HEADER_LENGTH;
- else
- header_length = DTLS1_HM_HEADER_LENGTH;
-
- memcpy(s->init_buf->data, frag->fragment,
- frag->msg_header.msg_len + header_length);
- s->init_num = frag->msg_header.msg_len + header_length;
-
- dtls1_set_message_header_int(s, frag->msg_header.type,
- frag->msg_header.msg_len,
- frag->msg_header.seq, 0,
- frag->msg_header.frag_len);
-
- /* save current state */
- saved_state.enc_write_ctx = s->enc_write_ctx;
- saved_state.write_hash = s->write_hash;
- saved_state.compress = s->compress;
- saved_state.session = s->session;
- saved_state.epoch = DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
-
- s->d1->retransmitting = 1;
-
- /* restore state in which the message was originally sent */
- s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
- s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
- s->compress = frag->msg_header.saved_retransmit_state.compress;
- s->session = frag->msg_header.saved_retransmit_state.session;
- DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer,
- frag->msg_header.
- saved_retransmit_state.epoch);
-
- ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
- SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
-
- /* restore current state */
- s->enc_write_ctx = saved_state.enc_write_ctx;
- s->write_hash = saved_state.write_hash;
- s->compress = saved_state.compress;
- s->session = saved_state.session;
- DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, saved_state.epoch);
-
- s->d1->retransmitting = 0;
-
- (void)BIO_flush(s->wbio);
- return ret;
-}
-
-void dtls1_set_message_header(SSL *s,
- unsigned char mt, size_t len,
- size_t frag_off, size_t frag_len)
-{
- if (frag_off == 0) {
- s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
- s->d1->next_handshake_write_seq++;
- }
-
- dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
- frag_off, frag_len);
-}
-
-/* don't actually do the writing, wait till the MTU has been retrieved */
-static void
-dtls1_set_message_header_int(SSL *s, unsigned char mt,
- size_t len, unsigned short seq_num,
- size_t frag_off, size_t frag_len)
-{
- struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-
- msg_hdr->type = mt;
- msg_hdr->msg_len = len;
- msg_hdr->seq = seq_num;
- msg_hdr->frag_off = frag_off;
- msg_hdr->frag_len = frag_len;
-}
-
-static void
-dtls1_fix_message_header(SSL *s, size_t frag_off, size_t frag_len)
-{
- struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-
- msg_hdr->frag_off = frag_off;
- msg_hdr->frag_len = frag_len;
-}
-
-static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p)
-{
- struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-
- *p++ = msg_hdr->type;
- l2n3(msg_hdr->msg_len, p);
-
- s2n(msg_hdr->seq, p);
- l2n3(msg_hdr->frag_off, p);
- l2n3(msg_hdr->frag_len, p);
-
- return p;
-}
-
-void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
-{
- memset(msg_hdr, 0, sizeof(*msg_hdr));
- msg_hdr->type = *(data++);
- n2l3(data, msg_hdr->msg_len);
-
- n2s(data, msg_hdr->seq);
- n2l3(data, msg_hdr->frag_off);
- n2l3(data, msg_hdr->frag_len);
-}
-
-int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype)
-{
- unsigned char *header;
-
- if (htype == SSL3_MT_CHANGE_CIPHER_SPEC) {
- s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
- dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
- s->d1->handshake_write_seq, 0, 0);
- if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS))
- return 0;
- } else {
- dtls1_set_message_header(s, htype, 0, 0, 0);
- /*
- * We allocate space at the start for the message header. This gets
- * filled in later
- */
- if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header)
- || !WPACKET_start_sub_packet(pkt))
- return 0;
- }
-
- return 1;
-}
-
-int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
-{
- size_t msglen;
-
- if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
- || !WPACKET_get_length(pkt, &msglen)
- || msglen > INT_MAX)
- return 0;
-
- if (htype != SSL3_MT_CHANGE_CIPHER_SPEC) {
- s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH;
- s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH;
- }
- s->init_num = (int)msglen;
- s->init_off = 0;
-
- if (htype != DTLS1_MT_HELLO_VERIFY_REQUEST) {
- /* Buffer the message to handle re-xmits */
- if (!dtls1_buffer_message(s, htype == SSL3_MT_CHANGE_CIPHER_SPEC
- ? 1 : 0))
- return 0;
- }
-
- return 1;
-}
+#include "internal/cryptlib.h"
+#include <openssl/buffer.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8)
+
+#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \
+ if ((end) - (start) <= 8) { \
+ long ii; \
+ for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \
+ } else { \
+ long ii; \
+ bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \
+ for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \
+ bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \
+ } }
+
+#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
+ long ii; \
+ is_complete = 1; \
+ if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
+ if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
+ if (bitmask[ii] != 0xff) { is_complete = 0; break; } }
+
+static unsigned char bitmask_start_values[] =
+ { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
+static unsigned char bitmask_end_values[] =
+ { 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
+
+static void dtls1_fix_message_header(SSL *s, size_t frag_off,
+ size_t frag_len);
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
+static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
+ size_t len,
+ unsigned short seq_num,
+ size_t frag_off,
+ size_t frag_len);
+static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len);
+
+static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly)
+{
+ hm_fragment *frag = NULL;
+ unsigned char *buf = NULL;
+ unsigned char *bitmask = NULL;
+
+ if ((frag = OPENSSL_malloc(sizeof(*frag))) == NULL) {
+ SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (frag_len) {
+ if ((buf = OPENSSL_malloc(frag_len)) == NULL) {
+ SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ }
+
+ /* zero length fragment gets zero frag->fragment */
+ frag->fragment = buf;
+
+ /* Initialize reassembly bitmask if necessary */
+ if (reassembly) {
+ bitmask = OPENSSL_zalloc(RSMBLY_BITMASK_SIZE(frag_len));
+ if (bitmask == NULL) {
+ SSLerr(SSL_F_DTLS1_HM_FRAGMENT_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(buf);
+ OPENSSL_free(frag);
+ return NULL;
+ }
+ }
+
+ frag->reassembly = bitmask;
+
+ return frag;
+}
+
+void dtls1_hm_fragment_free(hm_fragment *frag)
+{
+ if (!frag)
+ return;
+ if (frag->msg_header.is_ccs) {
+ EVP_CIPHER_CTX_free(frag->msg_header.
+ saved_retransmit_state.enc_write_ctx);
+ EVP_MD_CTX_free(frag->msg_header.saved_retransmit_state.write_hash);
+ }
+ OPENSSL_free(frag->fragment);
+ OPENSSL_free(frag->reassembly);
+ OPENSSL_free(frag);
+}
+
+/*
+ * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC)
+ */
+int dtls1_do_write(SSL *s, int type)
+{
+ int ret;
+ size_t written;
+ size_t curr_mtu;
+ int retry = 1;
+ size_t len, frag_off, mac_size, blocksize, used_len;
+
+ if (!dtls1_query_mtu(s))
+ return -1;
+
+ if (s->d1->mtu < dtls1_min_mtu(s))
+ /* should have something reasonable now */
+ return -1;
+
+ if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE) {
+ if (!ossl_assert(s->init_num ==
+ s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH))
+ return -1;
+ }
+
+ if (s->write_hash) {
+ if (s->enc_write_ctx
+ && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
+ EVP_CIPH_FLAG_AEAD_CIPHER) != 0)
+ mac_size = 0;
+ else
+ mac_size = EVP_MD_CTX_size(s->write_hash);
+ } else
+ mac_size = 0;
+
+ if (s->enc_write_ctx &&
+ (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE))
+ blocksize = 2 * EVP_CIPHER_CTX_block_size(s->enc_write_ctx);
+ else
+ blocksize = 0;
+
+ frag_off = 0;
+ s->rwstate = SSL_NOTHING;
+
+ /* s->init_num shouldn't ever be < 0...but just in case */
+ while (s->init_num > 0) {
+ if (type == SSL3_RT_HANDSHAKE && s->init_off != 0) {
+ /* We must be writing a fragment other than the first one */
+
+ if (frag_off > 0) {
+ /* This is the first attempt at writing out this fragment */
+
+ if (s->init_off <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * Each fragment that was already sent must at least have
+ * contained the message header plus one other byte.
+ * Therefore |init_off| must have progressed by at least
+ * |DTLS1_HM_HEADER_LENGTH + 1| bytes. If not something went
+ * wrong.
+ */
+ return -1;
+ }
+
+ /*
+ * Adjust |init_off| and |init_num| to allow room for a new
+ * message header for this fragment.
+ */
+ s->init_off -= DTLS1_HM_HEADER_LENGTH;
+ s->init_num += DTLS1_HM_HEADER_LENGTH;
+ } else {
+ /*
+ * We must have been called again after a retry so use the
+ * fragment offset from our last attempt. We do not need
+ * to adjust |init_off| and |init_num| as above, because
+ * that should already have been done before the retry.
+ */
+ frag_off = s->d1->w_msg_hdr.frag_off;
+ }
+ }
+
+ used_len = BIO_wpending(s->wbio) + DTLS1_RT_HEADER_LENGTH
+ + mac_size + blocksize;
+ if (s->d1->mtu > used_len)
+ curr_mtu = s->d1->mtu - used_len;
+ else
+ curr_mtu = 0;
+
+ if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * grr.. we could get an error if MTU picked was wrong
+ */
+ ret = BIO_flush(s->wbio);
+ if (ret <= 0) {
+ s->rwstate = SSL_WRITING;
+ return ret;
+ }
+ used_len = DTLS1_RT_HEADER_LENGTH + mac_size + blocksize;
+ if (s->d1->mtu > used_len + DTLS1_HM_HEADER_LENGTH) {
+ curr_mtu = s->d1->mtu - used_len;
+ } else {
+ /* Shouldn't happen */
+ return -1;
+ }
+ }
+
+ /*
+ * We just checked that s->init_num > 0 so this cast should be safe
+ */
+ if (((unsigned int)s->init_num) > curr_mtu)
+ len = curr_mtu;
+ else
+ len = s->init_num;
+
+ if (len > s->max_send_fragment)
+ len = s->max_send_fragment;
+
+ /*
+ * XDTLS: this function is too long. split out the CCS part
+ */
+ if (type == SSL3_RT_HANDSHAKE) {
+ if (len < DTLS1_HM_HEADER_LENGTH) {
+ /*
+ * len is so small that we really can't do anything sensible
+ * so fail
+ */
+ return -1;
+ }
+ dtls1_fix_message_header(s, frag_off, len - DTLS1_HM_HEADER_LENGTH);
+
+ dtls1_write_message_header(s,
+ (unsigned char *)&s->init_buf->
+ data[s->init_off]);
+ }
+
+ ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len,
+ &written);
+ if (ret < 0) {
+ /*
+ * might need to update MTU here, but we don't know which
+ * previous packet caused the failure -- so can't really
+ * retransmit anything. continue as if everything is fine and
+ * wait for an alert to handle the retransmit
+ */
+ if (retry && BIO_ctrl(SSL_get_wbio(s),
+ BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) {
+ if (!(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
+ if (!dtls1_query_mtu(s))
+ return -1;
+ /* Have one more go */
+ retry = 0;
+ } else
+ return -1;
+ } else {
+ return -1;
+ }
+ } else {
+
+ /*
+ * bad if this assert fails, only part of the handshake message
+ * got sent. but why would this happen?
+ */
+ if (!ossl_assert(len == written))
+ return -1;
+
+ if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) {
+ /*
+ * should not be done for 'Hello Request's, but in that case
+ * we'll ignore the result anyway
+ */
+ unsigned char *p =
+ (unsigned char *)&s->init_buf->data[s->init_off];
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+ size_t xlen;
+
+ if (frag_off == 0 && s->version != DTLS1_BAD_VER) {
+ /*
+ * reconstruct message header is if it is being sent in
+ * single fragment
+ */
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_hdr->msg_len, p);
+ p -= DTLS1_HM_HEADER_LENGTH;
+ xlen = written;
+ } else {
+ p += DTLS1_HM_HEADER_LENGTH;
+ xlen = written - DTLS1_HM_HEADER_LENGTH;
+ }
+
+ if (!ssl3_finish_mac(s, p, xlen))
+ return -1;
+ }
+
+ if (written == s->init_num) {
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, type, s->init_buf->data,
+ (size_t)(s->init_off + s->init_num), s,
+ s->msg_callback_arg);
+
+ s->init_off = 0; /* done writing this message */
+ s->init_num = 0;
+
+ return 1;
+ }
+ s->init_off += written;
+ s->init_num -= written;
+ written -= DTLS1_HM_HEADER_LENGTH;
+ frag_off += written;
+
+ /*
+ * We save the fragment offset for the next fragment so we have it
+ * available in case of an IO retry. We don't know the length of the
+ * next fragment yet so just set that to 0 for now. It will be
+ * updated again later.
+ */
+ dtls1_fix_message_header(s, frag_off, 0);
+ }
+ }
+ return 0;
+}
+
+int dtls_get_message(SSL *s, int *mt, size_t *len)
+{
+ struct hm_header_st *msg_hdr;
+ unsigned char *p;
+ size_t msg_len;
+ size_t tmplen;
+ int errtype;
+
+ msg_hdr = &s->d1->r_msg_hdr;
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+
+ again:
+ if (!dtls_get_reassembled_message(s, &errtype, &tmplen)) {
+ if (errtype == DTLS1_HM_BAD_FRAGMENT
+ || errtype == DTLS1_HM_FRAGMENT_RETRY) {
+ /* bad fragment received */
+ goto again;
+ }
+ return 0;
+ }
+
+ *mt = s->s3->tmp.message_type;
+
+ p = (unsigned char *)s->init_buf->data;
+ *len = s->init_num;
+
+ if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ if (s->msg_callback) {
+ s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC,
+ p, 1, s, s->msg_callback_arg);
+ }
+ /*
+ * This isn't a real handshake message so skip the processing below.
+ */
+ return 1;
+ }
+
+ msg_len = msg_hdr->msg_len;
+
+ /* reconstruct message header */
+ *(p++) = msg_hdr->type;
+ l2n3(msg_len, p);
+ s2n(msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_len, p);
+ if (s->version != DTLS1_BAD_VER) {
+ p -= DTLS1_HM_HEADER_LENGTH;
+ msg_len += DTLS1_HM_HEADER_LENGTH;
+ }
+
+ /*
+ * If receiving Finished, record MAC of prior handshake messages for
+ * Finished verification.
+ */
+ if (*mt == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ if (!ssl3_finish_mac(s, p, msg_len))
+ return 0;
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ p, msg_len, s, s->msg_callback_arg);
+
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+
+ s->d1->handshake_read_seq++;
+
+ s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+
+ return 1;
+}
+
+/*
+ * dtls1_max_handshake_message_len returns the maximum number of bytes
+ * permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
+ * may be greater if the maximum certificate list size requires it.
+ */
+static size_t dtls1_max_handshake_message_len(const SSL *s)
+{
+ size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ if (max_len < s->max_cert_list)
+ return s->max_cert_list;
+ return max_len;
+}
+
+static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
+{
+ size_t frag_off, frag_len, msg_len;
+
+ msg_len = msg_hdr->msg_len;
+ frag_off = msg_hdr->frag_off;
+ frag_len = msg_hdr->frag_len;
+
+ /* sanity checking */
+ if ((frag_off + frag_len) > msg_len
+ || msg_len > dtls1_max_handshake_message_len(s)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
+ SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return 0;
+ }
+
+ if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
+ /*
+ * msg_len is limited to 2^24, but is effectively checked against
+ * dtls_max_handshake_message_len(s) above
+ */
+ if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
+ ERR_R_BUF_LIB);
+ return 0;
+ }
+
+ s->s3->tmp.message_size = msg_len;
+ s->d1->r_msg_hdr.msg_len = msg_len;
+ s->s3->tmp.message_type = msg_hdr->type;
+ s->d1->r_msg_hdr.type = msg_hdr->type;
+ s->d1->r_msg_hdr.seq = msg_hdr->seq;
+ } else if (msg_len != s->d1->r_msg_hdr.msg_len) {
+ /*
+ * They must be playing with us! BTW, failure to enforce upper limit
+ * would open possibility for buffer overrun.
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
+ SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Returns 1 if there is a buffered fragment available, 0 if not, or -1 on a
+ * fatal error.
+ */
+static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
+{
+ /*-
+ * (0) check whether the desired fragment is available
+ * if so:
+ * (1) copy over the fragment to s->init_buf->data[]
+ * (2) update s->init_num
+ */
+ pitem *item;
+ hm_fragment *frag;
+ int ret;
+
+ do {
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.seq < s->d1->handshake_read_seq) {
+ /* This is a stale message that has been buffered so clear it */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ }
+ } while (item == NULL);
+
+ /* Don't return if reassembly still in progress */
+ if (frag->reassembly != NULL)
+ return 0;
+
+ if (s->d1->handshake_read_seq == frag->msg_header.seq) {
+ size_t frag_len = frag->msg_header.frag_len;
+ pqueue_pop(s->d1->buffered_messages);
+
+ /* Calls SSLfatal() as required */
+ ret = dtls1_preprocess_fragment(s, &frag->msg_header);
+
+ if (ret && frag->msg_header.frag_len > 0) {
+ unsigned char *p =
+ (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+ memcpy(&p[frag->msg_header.frag_off], frag->fragment,
+ frag->msg_header.frag_len);
+ }
+
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+
+ if (ret) {
+ *len = frag_len;
+ return 1;
+ }
+
+ /* Fatal error */
+ s->init_num = 0;
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+static int
+dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr)
+{
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ int i = -1, is_complete;
+ unsigned char seq64be[8];
+ size_t frag_len = msg_hdr->frag_len;
+ size_t readbytes;
+
+ if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
+ msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
+ if (frag_len == 0) {
+ return DTLS1_HM_FRAGMENT_RETRY;
+ }
+
+ /* Try to find item in queue */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
+ seq64be[7] = (unsigned char)msg_hdr->seq;
+ item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+ if (item == NULL) {
+ frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1);
+ if (frag == NULL)
+ goto err;
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+ frag->msg_header.frag_len = frag->msg_header.msg_len;
+ frag->msg_header.frag_off = 0;
+ } else {
+ frag = (hm_fragment *)item->data;
+ if (frag->msg_header.msg_len != msg_hdr->msg_len) {
+ item = NULL;
+ frag = NULL;
+ goto err;
+ }
+ }
+
+ /*
+ * If message is already reassembled, this must be a retransmit and can
+ * be dropped. In this case item != NULL and so frag does not need to be
+ * freed.
+ */
+ if (frag->reassembly == NULL) {
+ unsigned char devnull[256];
+
+ while (frag_len) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ devnull,
+ frag_len >
+ sizeof(devnull) ? sizeof(devnull) :
+ frag_len, 0, &readbytes);
+ if (i <= 0)
+ goto err;
+ frag_len -= readbytes;
+ }
+ return DTLS1_HM_FRAGMENT_RETRY;
+ }
+
+ /* read the body of the fragment (header has already been read */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ frag->fragment + msg_hdr->frag_off,
+ frag_len, 0, &readbytes);
+ if (i <= 0 || readbytes != frag_len)
+ i = -1;
+ if (i <= 0)
+ goto err;
+
+ RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
+ (long)(msg_hdr->frag_off + frag_len));
+
+ if (!ossl_assert(msg_hdr->msg_len > 0))
+ goto err;
+ RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
+ is_complete);
+
+ if (is_complete) {
+ OPENSSL_free(frag->reassembly);
+ frag->reassembly = NULL;
+ }
+
+ if (item == NULL) {
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ i = -1;
+ goto err;
+ }
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /*
+ * pqueue_insert fails iff a duplicate item is inserted. However,
+ * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
+ * would have returned it and control would never have reached this
+ * branch.
+ */
+ if (!ossl_assert(item != NULL))
+ goto err;
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ err:
+ if (item == NULL)
+ dtls1_hm_fragment_free(frag);
+ return -1;
+}
+
+static int
+dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr)
+{
+ int i = -1;
+ hm_fragment *frag = NULL;
+ pitem *item = NULL;
+ unsigned char seq64be[8];
+ size_t frag_len = msg_hdr->frag_len;
+ size_t readbytes;
+
+ if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
+ goto err;
+
+ /* Try to find item in queue, to prevent duplicate entries */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(msg_hdr->seq >> 8);
+ seq64be[7] = (unsigned char)msg_hdr->seq;
+ item = pqueue_find(s->d1->buffered_messages, seq64be);
+
+ /*
+ * If we already have an entry and this one is a fragment, don't discard
+ * it and rather try to reassemble it.
+ */
+ if (item != NULL && frag_len != msg_hdr->msg_len)
+ item = NULL;
+
+ /*
+ * Discard the message if sequence number was already there, is too far
+ * in the future, already in the queue or if we received a FINISHED
+ * before the SERVER_HELLO, which then must be a stale retransmit.
+ */
+ if (msg_hdr->seq <= s->d1->handshake_read_seq ||
+ msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL ||
+ (s->d1->handshake_read_seq == 0 && msg_hdr->type == SSL3_MT_FINISHED)) {
+ unsigned char devnull[256];
+
+ while (frag_len) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ devnull,
+ frag_len >
+ sizeof(devnull) ? sizeof(devnull) :
+ frag_len, 0, &readbytes);
+ if (i <= 0)
+ goto err;
+ frag_len -= readbytes;
+ }
+ } else {
+ if (frag_len != msg_hdr->msg_len) {
+ return dtls1_reassemble_fragment(s, msg_hdr);
+ }
+
+ if (frag_len > dtls1_max_handshake_message_len(s))
+ goto err;
+
+ frag = dtls1_hm_fragment_new(frag_len, 0);
+ if (frag == NULL)
+ goto err;
+
+ memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+
+ if (frag_len) {
+ /*
+ * read the body of the fragment (header has already been read
+ */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ frag->fragment, frag_len, 0,
+ &readbytes);
+ if (i<=0 || readbytes != frag_len)
+ i = -1;
+ if (i <= 0)
+ goto err;
+ }
+
+ item = pitem_new(seq64be, frag);
+ if (item == NULL)
+ goto err;
+
+ item = pqueue_insert(s->d1->buffered_messages, item);
+ /*
+ * pqueue_insert fails iff a duplicate item is inserted. However,
+ * |item| cannot be a duplicate. If it were, |pqueue_find|, above,
+ * would have returned it. Then, either |frag_len| !=
+ * |msg_hdr->msg_len| in which case |item| is set to NULL and it will
+ * have been processed with |dtls1_reassemble_fragment|, above, or
+ * the record will have been discarded.
+ */
+ if (!ossl_assert(item != NULL))
+ goto err;
+ }
+
+ return DTLS1_HM_FRAGMENT_RETRY;
+
+ err:
+ if (item == NULL)
+ dtls1_hm_fragment_free(frag);
+ return 0;
+}
+
+static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
+{
+ unsigned char wire[DTLS1_HM_HEADER_LENGTH];
+ size_t mlen, frag_off, frag_len;
+ int i, ret, recvd_type;
+ struct hm_header_st msg_hdr;
+ size_t readbytes;
+
+ *errtype = 0;
+
+ redo:
+ /* see if we have the required fragment already */
+ ret = dtls1_retrieve_buffered_fragment(s, &frag_len);
+ if (ret < 0) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ if (ret > 0) {
+ s->init_num = frag_len;
+ *len = frag_len;
+ return 1;
+ }
+
+ /* read handshake message header */
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, wire,
+ DTLS1_HM_HEADER_LENGTH, 0, &readbytes);
+ if (i <= 0) { /* nbio, or an error */
+ s->rwstate = SSL_READING;
+ *len = 0;
+ return 0;
+ }
+ if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ if (wire[0] != SSL3_MT_CCS) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ goto f_err;
+ }
+
+ memcpy(s->init_buf->data, wire, readbytes);
+ s->init_num = readbytes - 1;
+ s->init_msg = s->init_buf->data + 1;
+ s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
+ s->s3->tmp.message_size = readbytes - 1;
+ *len = readbytes - 1;
+ return 1;
+ }
+
+ /* Handshake fails if message header is incomplete */
+ if (readbytes != DTLS1_HM_HEADER_LENGTH) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /* parse the message fragment header */
+ dtls1_get_message_header(wire, &msg_hdr);
+
+ mlen = msg_hdr.msg_len;
+ frag_off = msg_hdr.frag_off;
+ frag_len = msg_hdr.frag_len;
+
+ /*
+ * We must have at least frag_len bytes left in the record to be read.
+ * Fragments must not span records.
+ */
+ if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
+ goto f_err;
+ }
+
+ /*
+ * if this is a future (or stale) message it gets buffered
+ * (or dropped)--no further processing at this time
+ * While listening, we accept seq 1 (ClientHello with cookie)
+ * although we're still expecting seq 0 (ClientHello)
+ */
+ if (msg_hdr.seq != s->d1->handshake_read_seq) {
+ *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr);
+ return 0;
+ }
+
+ if (frag_len && frag_len < mlen) {
+ *errtype = dtls1_reassemble_fragment(s, &msg_hdr);
+ return 0;
+ }
+
+ if (!s->server
+ && s->d1->r_msg_hdr.frag_off == 0
+ && s->statem.hand_state != TLS_ST_OK
+ && wire[0] == SSL3_MT_HELLO_REQUEST) {
+ /*
+ * The server may always send 'Hello Request' messages -- we are
+ * doing a handshake anyway now, so ignore them if their format is
+ * correct. Does not count for 'Finished' MAC.
+ */
+ if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) {
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ wire, DTLS1_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
+
+ s->init_num = 0;
+ goto redo;
+ } else { /* Incorrectly formatted Hello request */
+
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+ }
+
+ if (!dtls1_preprocess_fragment(s, &msg_hdr)) {
+ /* SSLfatal() already called */
+ goto f_err;
+ }
+
+ if (frag_len > 0) {
+ unsigned char *p =
+ (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ &p[frag_off], frag_len, 0, &readbytes);
+
+ /*
+ * This shouldn't ever fail due to NBIO because we already checked
+ * that we have enough data in the record
+ */
+ if (i <= 0) {
+ s->rwstate = SSL_READING;
+ *len = 0;
+ return 0;
+ }
+ } else {
+ readbytes = 0;
+ }
+
+ /*
+ * XDTLS: an incorrectly formatted fragment should cause the handshake
+ * to fail
+ */
+ if (readbytes != frag_len) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
+ goto f_err;
+ }
+
+ /*
+ * Note that s->init_num is *not* used as current offset in
+ * s->init_buf->data, but as a counter summing up fragments' lengths: as
+ * soon as they sum up to handshake packet length, we assume we have got
+ * all the fragments.
+ */
+ *len = s->init_num = frag_len;
+ return 1;
+
+ f_err:
+ s->init_num = 0;
+ *len = 0;
+ return 0;
+}
+
+/*-
+ * for these 2 messages, we need to
+ * ssl->enc_read_ctx re-init
+ * ssl->rlayer.read_sequence zero
+ * ssl->s3->read_mac_secret re-init
+ * ssl->session->read_sym_enc assign
+ * ssl->session->read_compression assign
+ * ssl->session->read_hash assign
+ */
+int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
+{
+ if (s->version == DTLS1_BAD_VER) {
+ s->d1->next_handshake_write_seq++;
+
+ if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SCTP
+/*
+ * Wait for a dry event. Should only be called at a point in the handshake
+ * where we are not expecting any data from the peer except an alert.
+ */
+WORK_STATE dtls_wait_for_dry(SSL *s)
+{
+ int ret, errtype;
+ size_t len;
+
+ /* read app data until dry event */
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS_WAIT_FOR_DRY,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+ }
+
+ if (ret == 0) {
+ /*
+ * We're not expecting any more messages from the peer at this point -
+ * but we could get an alert. If an alert is waiting then we will never
+ * return successfully. Therefore we attempt to read a message. This
+ * should never succeed but will process any waiting alerts.
+ */
+ if (dtls_get_reassembled_message(s, &errtype, &len)) {
+ /* The call succeeded! This should never happen */
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_DTLS_WAIT_FOR_DRY,
+ SSL_R_UNEXPECTED_MESSAGE);
+ return WORK_ERROR;
+ }
+
+ s->s3->in_read_app_data = 2;
+ s->rwstate = SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ return WORK_MORE_A;
+ }
+ return WORK_FINISHED_CONTINUE;
+}
+#endif
+
+int dtls1_read_failed(SSL *s, int code)
+{
+ if (code > 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!dtls1_is_timer_expired(s) || ossl_statem_in_error(s)) {
+ /*
+ * not a timeout, none of our business, let higher layers handle
+ * this. in fact it's probably an error
+ */
+ return code;
+ }
+ /* done, no need to send a retransmit */
+ if (!SSL_in_init(s))
+ {
+ BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
+ return code;
+ }
+
+ return dtls1_handle_timeout(s);
+}
+
+int dtls1_get_queue_priority(unsigned short seq, int is_ccs)
+{
+ /*
+ * The index of the retransmission queue actually is the message sequence
+ * number, since the queue only contains messages of a single handshake.
+ * However, the ChangeCipherSpec has no message sequence number and so
+ * using only the sequence will result in the CCS and Finished having the
+ * same index. To prevent this, the sequence number is multiplied by 2.
+ * In case of a CCS 1 is subtracted. This does not only differ CSS and
+ * Finished, it also maintains the order of the index (important for
+ * priority queues) and fits in the unsigned short variable.
+ */
+ return seq * 2 - is_ccs;
+}
+
+int dtls1_retransmit_buffered_messages(SSL *s)
+{
+ pqueue *sent = s->d1->sent_messages;
+ piterator iter;
+ pitem *item;
+ hm_fragment *frag;
+ int found = 0;
+
+ iter = pqueue_iterator(sent);
+
+ for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) {
+ frag = (hm_fragment *)item->data;
+ if (dtls1_retransmit_message(s, (unsigned short)
+ dtls1_get_queue_priority
+ (frag->msg_header.seq,
+ frag->msg_header.is_ccs), &found) <= 0)
+ return -1;
+ }
+
+ return 1;
+}
+
+int dtls1_buffer_message(SSL *s, int is_ccs)
+{
+ pitem *item;
+ hm_fragment *frag;
+ unsigned char seq64be[8];
+
+ /*
+ * this function is called immediately after a message has been
+ * serialized
+ */
+ if (!ossl_assert(s->init_off == 0))
+ return 0;
+
+ frag = dtls1_hm_fragment_new(s->init_num, 0);
+ if (frag == NULL)
+ return 0;
+
+ memcpy(frag->fragment, s->init_buf->data, s->init_num);
+
+ if (is_ccs) {
+ /* For DTLS1_BAD_VER the header length is non-standard */
+ if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
+ ((s->version ==
+ DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH)
+ == (unsigned int)s->init_num))
+ return 0;
+ } else {
+ if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
+ DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num))
+ return 0;
+ }
+
+ frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
+ frag->msg_header.seq = s->d1->w_msg_hdr.seq;
+ frag->msg_header.type = s->d1->w_msg_hdr.type;
+ frag->msg_header.frag_off = 0;
+ frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
+ frag->msg_header.is_ccs = is_ccs;
+
+ /* save current state */
+ frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
+ frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
+ frag->msg_header.saved_retransmit_state.compress = s->compress;
+ frag->msg_header.saved_retransmit_state.session = s->session;
+ frag->msg_header.saved_retransmit_state.epoch =
+ DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
+
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] =
+ (unsigned
+ char)(dtls1_get_queue_priority(frag->msg_header.seq,
+ frag->msg_header.is_ccs) >> 8);
+ seq64be[7] =
+ (unsigned
+ char)(dtls1_get_queue_priority(frag->msg_header.seq,
+ frag->msg_header.is_ccs));
+
+ item = pitem_new(seq64be, frag);
+ if (item == NULL) {
+ dtls1_hm_fragment_free(frag);
+ return 0;
+ }
+
+ pqueue_insert(s->d1->sent_messages, item);
+ return 1;
+}
+
+int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
+{
+ int ret;
+ /* XDTLS: for now assuming that read/writes are blocking */
+ pitem *item;
+ hm_fragment *frag;
+ unsigned long header_length;
+ unsigned char seq64be[8];
+ struct dtls1_retransmit_state saved_state;
+
+ /* XDTLS: the requested message ought to be found, otherwise error */
+ memset(seq64be, 0, sizeof(seq64be));
+ seq64be[6] = (unsigned char)(seq >> 8);
+ seq64be[7] = (unsigned char)seq;
+
+ item = pqueue_find(s->d1->sent_messages, seq64be);
+ if (item == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_RETRANSMIT_MESSAGE,
+ ERR_R_INTERNAL_ERROR);
+ *found = 0;
+ return 0;
+ }
+
+ *found = 1;
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.is_ccs)
+ header_length = DTLS1_CCS_HEADER_LENGTH;
+ else
+ header_length = DTLS1_HM_HEADER_LENGTH;
+
+ memcpy(s->init_buf->data, frag->fragment,
+ frag->msg_header.msg_len + header_length);
+ s->init_num = frag->msg_header.msg_len + header_length;
+
+ dtls1_set_message_header_int(s, frag->msg_header.type,
+ frag->msg_header.msg_len,
+ frag->msg_header.seq, 0,
+ frag->msg_header.frag_len);
+
+ /* save current state */
+ saved_state.enc_write_ctx = s->enc_write_ctx;
+ saved_state.write_hash = s->write_hash;
+ saved_state.compress = s->compress;
+ saved_state.session = s->session;
+ saved_state.epoch = DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer);
+
+ s->d1->retransmitting = 1;
+
+ /* restore state in which the message was originally sent */
+ s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
+ s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
+ s->compress = frag->msg_header.saved_retransmit_state.compress;
+ s->session = frag->msg_header.saved_retransmit_state.session;
+ DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer,
+ frag->msg_header.
+ saved_retransmit_state.epoch);
+
+ ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
+ SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+
+ /* restore current state */
+ s->enc_write_ctx = saved_state.enc_write_ctx;
+ s->write_hash = saved_state.write_hash;
+ s->compress = saved_state.compress;
+ s->session = saved_state.session;
+ DTLS_RECORD_LAYER_set_saved_w_epoch(&s->rlayer, saved_state.epoch);
+
+ s->d1->retransmitting = 0;
+
+ (void)BIO_flush(s->wbio);
+ return ret;
+}
+
+void dtls1_set_message_header(SSL *s,
+ unsigned char mt, size_t len,
+ size_t frag_off, size_t frag_len)
+{
+ if (frag_off == 0) {
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ s->d1->next_handshake_write_seq++;
+ }
+
+ dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
+ frag_off, frag_len);
+}
+
+/* don't actually do the writing, wait till the MTU has been retrieved */
+static void
+dtls1_set_message_header_int(SSL *s, unsigned char mt,
+ size_t len, unsigned short seq_num,
+ size_t frag_off, size_t frag_len)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ msg_hdr->type = mt;
+ msg_hdr->msg_len = len;
+ msg_hdr->seq = seq_num;
+ msg_hdr->frag_off = frag_off;
+ msg_hdr->frag_len = frag_len;
+}
+
+static void
+dtls1_fix_message_header(SSL *s, size_t frag_off, size_t frag_len)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ msg_hdr->frag_off = frag_off;
+ msg_hdr->frag_len = frag_len;
+}
+
+static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p)
+{
+ struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+
+ s2n(msg_hdr->seq, p);
+ l2n3(msg_hdr->frag_off, p);
+ l2n3(msg_hdr->frag_len, p);
+
+ return p;
+}
+
+void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
+{
+ memset(msg_hdr, 0, sizeof(*msg_hdr));
+ msg_hdr->type = *(data++);
+ n2l3(data, msg_hdr->msg_len);
+
+ n2s(data, msg_hdr->seq);
+ n2l3(data, msg_hdr->frag_off);
+ n2l3(data, msg_hdr->frag_len);
+}
+
+int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype)
+{
+ unsigned char *header;
+
+ if (htype == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+ dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
+ s->d1->handshake_write_seq, 0, 0);
+ if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS))
+ return 0;
+ } else {
+ dtls1_set_message_header(s, htype, 0, 0, 0);
+ /*
+ * We allocate space at the start for the message header. This gets
+ * filled in later
+ */
+ if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header)
+ || !WPACKET_start_sub_packet(pkt))
+ return 0;
+ }
+
+ return 1;
+}
+
+int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
+{
+ size_t msglen;
+
+ if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
+ || !WPACKET_get_length(pkt, &msglen)
+ || msglen > INT_MAX)
+ return 0;
+
+ if (htype != SSL3_MT_CHANGE_CIPHER_SPEC) {
+ s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH;
+ s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH;
+ }
+ s->init_num = (int)msglen;
+ s->init_off = 0;
+
+ if (htype != DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ /* Buffer the message to handle re-xmits */
+ if (!dtls1_buffer_message(s, htype == SSL3_MT_CHANGE_CIPHER_SPEC
+ ? 1 : 0))
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/contrib/libs/openssl/ssl/statem/statem_lib.c b/contrib/libs/openssl/ssl/statem/statem_lib.c
index c3b6f8f456..b4c56913ab 100644
--- a/contrib/libs/openssl/ssl/statem/statem_lib.c
+++ b/contrib/libs/openssl/ssl/statem/statem_lib.c
@@ -1,173 +1,173 @@
-/*
+/*
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2002, Oracle and/or its affiliates. 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 <limits.h>
-#include <string.h>
-#include <stdio.h>
+ * Copyright (c) 2002, Oracle and/or its affiliates. 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 <limits.h>
+#include <string.h>
+#include <stdio.h>
#include "../ssl_local.h"
#include "statem_local.h"
-#include "internal/cryptlib.h"
-#include <openssl/buffer.h>
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-
-/*
- * Map error codes to TLS/SSL alart types.
- */
-typedef struct x509err2alert_st {
- int x509err;
- int alert;
-} X509ERR2ALERT;
-
-/* Fixed value used in the ServerHello random field to identify an HRR */
-const unsigned char hrrrandom[] = {
- 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02,
- 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
- 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
-};
-
-/*
- * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
- * SSL3_RT_CHANGE_CIPHER_SPEC)
- */
-int ssl3_do_write(SSL *s, int type)
-{
- int ret;
- size_t written = 0;
-
- ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
- s->init_num, &written);
- if (ret < 0)
- return -1;
- if (type == SSL3_RT_HANDSHAKE)
- /*
- * should not be done for 'Hello Request's, but in that case we'll
- * ignore the result anyway
- * TLS1.3 KeyUpdate and NewSessionTicket do not need to be added
- */
- if (!SSL_IS_TLS13(s) || (s->statem.hand_state != TLS_ST_SW_SESSION_TICKET
- && s->statem.hand_state != TLS_ST_CW_KEY_UPDATE
- && s->statem.hand_state != TLS_ST_SW_KEY_UPDATE))
- if (!ssl3_finish_mac(s,
- (unsigned char *)&s->init_buf->data[s->init_off],
- written))
- return -1;
- if (written == s->init_num) {
- if (s->msg_callback)
- s->msg_callback(1, s->version, type, s->init_buf->data,
- (size_t)(s->init_off + s->init_num), s,
- s->msg_callback_arg);
- return 1;
- }
- s->init_off += written;
- s->init_num -= written;
- return 0;
-}
-
-int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
-{
- size_t msglen;
-
- if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
- || !WPACKET_get_length(pkt, &msglen)
- || msglen > INT_MAX)
- return 0;
- s->init_num = (int)msglen;
- s->init_off = 0;
-
- return 1;
-}
-
-int tls_setup_handshake(SSL *s)
-{
- if (!ssl3_init_finished_mac(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /* Reset any extension flags */
- memset(s->ext.extflags, 0, sizeof(s->ext.extflags));
-
- if (s->server) {
- STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(s);
- int i, ver_min, ver_max, ok = 0;
-
- /*
- * Sanity check that the maximum version we accept has ciphers
- * enabled. For clients we do this check during construction of the
- * ClientHello.
- */
- if (ssl_get_min_max_version(s, &ver_min, &ver_max, NULL) != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
- const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
-
- if (SSL_IS_DTLS(s)) {
- if (DTLS_VERSION_GE(ver_max, c->min_dtls) &&
- DTLS_VERSION_LE(ver_max, c->max_dtls))
- ok = 1;
- } else if (ver_max >= c->min_tls && ver_max <= c->max_tls) {
- ok = 1;
- }
- if (ok)
- break;
- }
- if (!ok) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
- SSL_R_NO_CIPHERS_AVAILABLE);
- ERR_add_error_data(1, "No ciphers enabled for max supported "
- "SSL/TLS version");
- return 0;
- }
- if (SSL_IS_FIRST_HANDSHAKE(s)) {
- /* N.B. s->session_ctx == s->ctx here */
- tsan_counter(&s->session_ctx->stats.sess_accept);
- } else {
- /* N.B. s->ctx may not equal s->session_ctx */
- tsan_counter(&s->ctx->stats.sess_accept_renegotiate);
-
- s->s3->tmp.cert_request = 0;
- }
- } else {
- if (SSL_IS_FIRST_HANDSHAKE(s))
- tsan_counter(&s->session_ctx->stats.sess_connect);
- else
- tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate);
-
- /* mark client_random uninitialized */
- memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
- s->hit = 0;
-
- s->s3->tmp.cert_req = 0;
-
- if (SSL_IS_DTLS(s))
- s->statem.use_timer = 1;
- }
-
- return 1;
-}
-
-/*
- * Size of the to-be-signed TLS13 data, without the hash size itself:
- * 64 bytes of value 32, 33 context bytes, 1 byte separator
- */
-#define TLS13_TBS_START_SIZE 64
-#define TLS13_TBS_PREAMBLE_SIZE (TLS13_TBS_START_SIZE + 33 + 1)
-
-static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
- void **hdata, size_t *hdatalen)
-{
+#include "internal/cryptlib.h"
+#include <openssl/buffer.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+/*
+ * Map error codes to TLS/SSL alart types.
+ */
+typedef struct x509err2alert_st {
+ int x509err;
+ int alert;
+} X509ERR2ALERT;
+
+/* Fixed value used in the ServerHello random field to identify an HRR */
+const unsigned char hrrrandom[] = {
+ 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02,
+ 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
+ 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
+};
+
+/*
+ * send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
+ * SSL3_RT_CHANGE_CIPHER_SPEC)
+ */
+int ssl3_do_write(SSL *s, int type)
+{
+ int ret;
+ size_t written = 0;
+
+ ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
+ s->init_num, &written);
+ if (ret < 0)
+ return -1;
+ if (type == SSL3_RT_HANDSHAKE)
+ /*
+ * should not be done for 'Hello Request's, but in that case we'll
+ * ignore the result anyway
+ * TLS1.3 KeyUpdate and NewSessionTicket do not need to be added
+ */
+ if (!SSL_IS_TLS13(s) || (s->statem.hand_state != TLS_ST_SW_SESSION_TICKET
+ && s->statem.hand_state != TLS_ST_CW_KEY_UPDATE
+ && s->statem.hand_state != TLS_ST_SW_KEY_UPDATE))
+ if (!ssl3_finish_mac(s,
+ (unsigned char *)&s->init_buf->data[s->init_off],
+ written))
+ return -1;
+ if (written == s->init_num) {
+ if (s->msg_callback)
+ s->msg_callback(1, s->version, type, s->init_buf->data,
+ (size_t)(s->init_off + s->init_num), s,
+ s->msg_callback_arg);
+ return 1;
+ }
+ s->init_off += written;
+ s->init_num -= written;
+ return 0;
+}
+
+int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
+{
+ size_t msglen;
+
+ if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
+ || !WPACKET_get_length(pkt, &msglen)
+ || msglen > INT_MAX)
+ return 0;
+ s->init_num = (int)msglen;
+ s->init_off = 0;
+
+ return 1;
+}
+
+int tls_setup_handshake(SSL *s)
+{
+ if (!ssl3_init_finished_mac(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ /* Reset any extension flags */
+ memset(s->ext.extflags, 0, sizeof(s->ext.extflags));
+
+ if (s->server) {
+ STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(s);
+ int i, ver_min, ver_max, ok = 0;
+
+ /*
+ * Sanity check that the maximum version we accept has ciphers
+ * enabled. For clients we do this check during construction of the
+ * ClientHello.
+ */
+ if (ssl_get_min_max_version(s, &ver_min, &ver_max, NULL) != 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
+ const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
+
+ if (SSL_IS_DTLS(s)) {
+ if (DTLS_VERSION_GE(ver_max, c->min_dtls) &&
+ DTLS_VERSION_LE(ver_max, c->max_dtls))
+ ok = 1;
+ } else if (ver_max >= c->min_tls && ver_max <= c->max_tls) {
+ ok = 1;
+ }
+ if (ok)
+ break;
+ }
+ if (!ok) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
+ SSL_R_NO_CIPHERS_AVAILABLE);
+ ERR_add_error_data(1, "No ciphers enabled for max supported "
+ "SSL/TLS version");
+ return 0;
+ }
+ if (SSL_IS_FIRST_HANDSHAKE(s)) {
+ /* N.B. s->session_ctx == s->ctx here */
+ tsan_counter(&s->session_ctx->stats.sess_accept);
+ } else {
+ /* N.B. s->ctx may not equal s->session_ctx */
+ tsan_counter(&s->ctx->stats.sess_accept_renegotiate);
+
+ s->s3->tmp.cert_request = 0;
+ }
+ } else {
+ if (SSL_IS_FIRST_HANDSHAKE(s))
+ tsan_counter(&s->session_ctx->stats.sess_connect);
+ else
+ tsan_counter(&s->session_ctx->stats.sess_connect_renegotiate);
+
+ /* mark client_random uninitialized */
+ memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
+ s->hit = 0;
+
+ s->s3->tmp.cert_req = 0;
+
+ if (SSL_IS_DTLS(s))
+ s->statem.use_timer = 1;
+ }
+
+ return 1;
+}
+
+/*
+ * Size of the to-be-signed TLS13 data, without the hash size itself:
+ * 64 bytes of value 32, 33 context bytes, 1 byte separator
+ */
+#define TLS13_TBS_START_SIZE 64
+#define TLS13_TBS_PREAMBLE_SIZE (TLS13_TBS_START_SIZE + 33 + 1)
+
+static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
+ void **hdata, size_t *hdatalen)
+{
#ifdef CHARSET_EBCDIC
static const char servercontext[] = { 0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e,
0x33, 0x2c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x65,
@@ -181,863 +181,863 @@ static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
static const char servercontext[] = "TLS 1.3, server CertificateVerify";
static const char clientcontext[] = "TLS 1.3, client CertificateVerify";
#endif
- if (SSL_IS_TLS13(s)) {
- size_t hashlen;
-
- /* Set the first 64 bytes of to-be-signed data to octet 32 */
- memset(tls13tbs, 32, TLS13_TBS_START_SIZE);
- /* This copies the 33 bytes of context plus the 0 separator byte */
- if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
- || s->statem.hand_state == TLS_ST_SW_CERT_VRFY)
- strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, servercontext);
- else
- strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, clientcontext);
-
- /*
- * If we're currently reading then we need to use the saved handshake
- * hash value. We can't use the current handshake hash state because
- * that includes the CertVerify itself.
- */
- if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
- || s->statem.hand_state == TLS_ST_SR_CERT_VRFY) {
- memcpy(tls13tbs + TLS13_TBS_PREAMBLE_SIZE, s->cert_verify_hash,
- s->cert_verify_hash_len);
- hashlen = s->cert_verify_hash_len;
- } else if (!ssl_handshake_hash(s, tls13tbs + TLS13_TBS_PREAMBLE_SIZE,
- EVP_MAX_MD_SIZE, &hashlen)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- *hdata = tls13tbs;
- *hdatalen = TLS13_TBS_PREAMBLE_SIZE + hashlen;
- } else {
- size_t retlen;
- long retlen_l;
-
- retlen = retlen_l = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
- if (retlen_l <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- *hdatalen = retlen;
- }
-
- return 1;
-}
-
-int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
-{
- EVP_PKEY *pkey = NULL;
- const EVP_MD *md = NULL;
- EVP_MD_CTX *mctx = NULL;
- EVP_PKEY_CTX *pctx = NULL;
- size_t hdatalen = 0, siglen = 0;
- void *hdata;
- unsigned char *sig = NULL;
- unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
- const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
-
- if (lu == NULL || s->s3->tmp.cert == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- pkey = s->s3->tmp.cert->privatekey;
-
- if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- mctx = EVP_MD_CTX_new();
- if (mctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Get the data to be signed */
- if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- siglen = EVP_PKEY_size(pkey);
- sig = OPENSSL_malloc(siglen);
- if (sig == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
- }
-
- if (lu->sig == EVP_PKEY_RSA_PSS) {
- if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
- || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
- RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
- }
- }
- if (s->version == SSL3_VERSION) {
- if (EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0
- || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
- (int)s->session->master_key_length,
- s->session->master_key)
- || EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
-
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
- }
- } else if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
- }
-
-#ifndef OPENSSL_NO_GOST
- {
- int pktype = lu->sig;
-
- if (pktype == NID_id_GostR3410_2001
- || pktype == NID_id_GostR3410_2012_256
- || pktype == NID_id_GostR3410_2012_512)
- BUF_reverse(sig, NULL, siglen);
- }
-#endif
-
- if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Digest cached records and discard handshake buffer */
- if (!ssl3_digest_cached_records(s, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- OPENSSL_free(sig);
- EVP_MD_CTX_free(mctx);
- return 1;
- err:
- OPENSSL_free(sig);
- EVP_MD_CTX_free(mctx);
- return 0;
-}
-
-MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
-{
- EVP_PKEY *pkey = NULL;
- const unsigned char *data;
-#ifndef OPENSSL_NO_GOST
- unsigned char *gost_data = NULL;
-#endif
- MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
- int j;
- unsigned int len;
- X509 *peer;
- const EVP_MD *md = NULL;
- size_t hdatalen = 0;
- void *hdata;
- unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
- EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- EVP_PKEY_CTX *pctx = NULL;
-
- if (mctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- peer = s->session->peer;
- pkey = X509_get0_pubkey(peer);
- if (pkey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
- goto err;
- }
-
- if (SSL_USE_SIGALGS(s)) {
- unsigned int sigalg;
-
- if (!PACKET_get_net_2(pkt, &sigalg)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_BAD_PACKET);
- goto err;
- }
- if (tls12_check_peer_sigalg(s, sigalg, pkey) <= 0) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
-#ifdef SSL_DEBUG
- if (SSL_USE_SIGALGS(s))
- fprintf(stderr, "USING TLSv1.2 HASH %s\n",
- md == NULL ? "n/a" : EVP_MD_name(md));
-#endif
-
- /* Check for broken implementations of GOST ciphersuites */
- /*
- * If key is GOST and len is exactly 64 or 128, it is signature without
- * length field (CryptoPro implementations at least till TLS 1.2)
- */
-#ifndef OPENSSL_NO_GOST
- if (!SSL_USE_SIGALGS(s)
- && ((PACKET_remaining(pkt) == 64
- && (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001
- || EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256))
- || (PACKET_remaining(pkt) == 128
- && EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) {
- len = PACKET_remaining(pkt);
- } else
-#endif
- if (!PACKET_get_net_2(pkt, &len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- j = EVP_PKEY_size(pkey);
- if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
- || (PACKET_remaining(pkt) == 0)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_WRONG_SIGNATURE_SIZE);
- goto err;
- }
- if (!PACKET_get_bytes(pkt, &data, len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
- /* SSLfatal() already called */
- goto err;
- }
-
-#ifdef SSL_DEBUG
- fprintf(stderr, "Using client verify alg %s\n",
- md == NULL ? "n/a" : EVP_MD_name(md));
-#endif
- if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
- }
-#ifndef OPENSSL_NO_GOST
- {
- int pktype = EVP_PKEY_id(pkey);
- if (pktype == NID_id_GostR3410_2001
- || pktype == NID_id_GostR3410_2012_256
- || pktype == NID_id_GostR3410_2012_512) {
- if ((gost_data = OPENSSL_malloc(len)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- BUF_reverse(gost_data, data, len);
- data = gost_data;
- }
- }
-#endif
-
- if (SSL_USE_PSS(s)) {
- if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
- || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
- RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
- }
- }
- if (s->version == SSL3_VERSION) {
- if (EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0
- || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
- (int)s->session->master_key_length,
- s->session->master_key)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- ERR_R_EVP_LIB);
- goto err;
- }
- if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_BAD_SIGNATURE);
- goto err;
- }
- } else {
- j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
- if (j <= 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
- SSL_R_BAD_SIGNATURE);
- goto err;
- }
- }
-
- /*
- * In TLSv1.3 on the client side we make sure we prepare the client
- * certificate after the CertVerify instead of when we get the
- * CertificateRequest. This is because in TLSv1.3 the CertificateRequest
- * comes *before* the Certificate message. In TLSv1.2 it comes after. We
- * want to make sure that SSL_get_peer_certificate() will return the actual
- * server certificate from the client_cert_cb callback.
- */
- if (!s->server && SSL_IS_TLS13(s) && s->s3->tmp.cert_req == 1)
- ret = MSG_PROCESS_CONTINUE_PROCESSING;
- else
- ret = MSG_PROCESS_CONTINUE_READING;
- err:
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
- EVP_MD_CTX_free(mctx);
-#ifndef OPENSSL_NO_GOST
- OPENSSL_free(gost_data);
-#endif
- return ret;
-}
-
-int tls_construct_finished(SSL *s, WPACKET *pkt)
-{
- size_t finish_md_len;
- const char *sender;
- size_t slen;
-
- /* This is a real handshake so make sure we clean it up at the end */
- if (!s->server && s->post_handshake_auth != SSL_PHA_REQUESTED)
- s->statem.cleanuphand = 1;
-
- /*
- * We only change the keys if we didn't already do this when we sent the
- * client certificate
- */
- if (SSL_IS_TLS13(s)
- && !s->server
- && s->s3->tmp.cert_req == 0
- && (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {;
- /* SSLfatal() already called */
- return 0;
- }
-
- if (s->server) {
- sender = s->method->ssl3_enc->server_finished_label;
- slen = s->method->ssl3_enc->server_finished_label_len;
- } else {
- sender = s->method->ssl3_enc->client_finished_label;
- slen = s->method->ssl3_enc->client_finished_label_len;
- }
-
- finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
- sender, slen,
- s->s3->tmp.finish_md);
- if (finish_md_len == 0) {
- /* SSLfatal() already called */
- return 0;
- }
-
- s->s3->tmp.finish_md_len = finish_md_len;
-
- if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * Log the master secret, if logging is enabled. We don't log it for
- * TLSv1.3: there's a different key schedule for that.
- */
- if (!SSL_IS_TLS13(s) && !ssl_log_secret(s, MASTER_SECRET_LABEL,
- s->session->master_key,
- s->session->master_key_length)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /*
- * Copy the finished so we can use it for renegotiation checks
- */
- if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!s->server) {
- memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md,
- finish_md_len);
- s->s3->previous_client_finished_len = finish_md_len;
- } else {
- memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md,
- finish_md_len);
- s->s3->previous_server_finished_len = finish_md_len;
- }
-
- return 1;
-}
-
-int tls_construct_key_update(SSL *s, WPACKET *pkt)
-{
- if (!WPACKET_put_bytes_u8(pkt, s->key_update)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- s->key_update = SSL_KEY_UPDATE_NONE;
- return 1;
-}
-
-MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
-{
- unsigned int updatetype;
-
- /*
- * A KeyUpdate message signals a key change so the end of the message must
- * be on a record boundary.
- */
- if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
- return MSG_PROCESS_ERROR;
- }
-
- if (!PACKET_get_1(pkt, &updatetype)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE,
- SSL_R_BAD_KEY_UPDATE);
- return MSG_PROCESS_ERROR;
- }
-
- /*
- * There are only two defined key update types. Fail if we get a value we
- * didn't recognise.
- */
- if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
- && updatetype != SSL_KEY_UPDATE_REQUESTED) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
- SSL_R_BAD_KEY_UPDATE);
- return MSG_PROCESS_ERROR;
- }
-
- /*
- * If we get a request for us to update our sending keys too then, we need
- * to additionally send a KeyUpdate message. However that message should
+ if (SSL_IS_TLS13(s)) {
+ size_t hashlen;
+
+ /* Set the first 64 bytes of to-be-signed data to octet 32 */
+ memset(tls13tbs, 32, TLS13_TBS_START_SIZE);
+ /* This copies the 33 bytes of context plus the 0 separator byte */
+ if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
+ || s->statem.hand_state == TLS_ST_SW_CERT_VRFY)
+ strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, servercontext);
+ else
+ strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, clientcontext);
+
+ /*
+ * If we're currently reading then we need to use the saved handshake
+ * hash value. We can't use the current handshake hash state because
+ * that includes the CertVerify itself.
+ */
+ if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
+ || s->statem.hand_state == TLS_ST_SR_CERT_VRFY) {
+ memcpy(tls13tbs + TLS13_TBS_PREAMBLE_SIZE, s->cert_verify_hash,
+ s->cert_verify_hash_len);
+ hashlen = s->cert_verify_hash_len;
+ } else if (!ssl_handshake_hash(s, tls13tbs + TLS13_TBS_PREAMBLE_SIZE,
+ EVP_MAX_MD_SIZE, &hashlen)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ *hdata = tls13tbs;
+ *hdatalen = TLS13_TBS_PREAMBLE_SIZE + hashlen;
+ } else {
+ size_t retlen;
+ long retlen_l;
+
+ retlen = retlen_l = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
+ if (retlen_l <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ *hdatalen = retlen;
+ }
+
+ return 1;
+}
+
+int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
+{
+ EVP_PKEY *pkey = NULL;
+ const EVP_MD *md = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ size_t hdatalen = 0, siglen = 0;
+ void *hdata;
+ unsigned char *sig = NULL;
+ unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
+ const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
+
+ if (lu == NULL || s->s3->tmp.cert == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ pkey = s->s3->tmp.cert->privatekey;
+
+ if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Get the data to be signed */
+ if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ siglen = EVP_PKEY_size(pkey);
+ sig = OPENSSL_malloc(siglen);
+ if (sig == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ if (lu->sig == EVP_PKEY_RSA_PSS) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
+ || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
+ RSA_PSS_SALTLEN_DIGEST) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ }
+ if (s->version == SSL3_VERSION) {
+ if (EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0
+ || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ (int)s->session->master_key_length,
+ s->session->master_key)
+ || EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
+
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ } else if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_GOST
+ {
+ int pktype = lu->sig;
+
+ if (pktype == NID_id_GostR3410_2001
+ || pktype == NID_id_GostR3410_2012_256
+ || pktype == NID_id_GostR3410_2012_512)
+ BUF_reverse(sig, NULL, siglen);
+ }
+#endif
+
+ if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Digest cached records and discard handshake buffer */
+ if (!ssl3_digest_cached_records(s, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ OPENSSL_free(sig);
+ EVP_MD_CTX_free(mctx);
+ return 1;
+ err:
+ OPENSSL_free(sig);
+ EVP_MD_CTX_free(mctx);
+ return 0;
+}
+
+MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
+{
+ EVP_PKEY *pkey = NULL;
+ const unsigned char *data;
+#ifndef OPENSSL_NO_GOST
+ unsigned char *gost_data = NULL;
+#endif
+ MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
+ int j;
+ unsigned int len;
+ X509 *peer;
+ const EVP_MD *md = NULL;
+ size_t hdatalen = 0;
+ void *hdata;
+ unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
+ EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+ EVP_PKEY_CTX *pctx = NULL;
+
+ if (mctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ peer = s->session->peer;
+ pkey = X509_get0_pubkey(peer);
+ if (pkey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
+ goto err;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ unsigned int sigalg;
+
+ if (!PACKET_get_net_2(pkt, &sigalg)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_BAD_PACKET);
+ goto err;
+ }
+ if (tls12_check_peer_sigalg(s, sigalg, pkey) <= 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+#ifdef SSL_DEBUG
+ if (SSL_USE_SIGALGS(s))
+ fprintf(stderr, "USING TLSv1.2 HASH %s\n",
+ md == NULL ? "n/a" : EVP_MD_name(md));
+#endif
+
+ /* Check for broken implementations of GOST ciphersuites */
+ /*
+ * If key is GOST and len is exactly 64 or 128, it is signature without
+ * length field (CryptoPro implementations at least till TLS 1.2)
+ */
+#ifndef OPENSSL_NO_GOST
+ if (!SSL_USE_SIGALGS(s)
+ && ((PACKET_remaining(pkt) == 64
+ && (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001
+ || EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256))
+ || (PACKET_remaining(pkt) == 128
+ && EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) {
+ len = PACKET_remaining(pkt);
+ } else
+#endif
+ if (!PACKET_get_net_2(pkt, &len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ j = EVP_PKEY_size(pkey);
+ if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
+ || (PACKET_remaining(pkt) == 0)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_WRONG_SIGNATURE_SIZE);
+ goto err;
+ }
+ if (!PACKET_get_bytes(pkt, &data, len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using client verify alg %s\n",
+ md == NULL ? "n/a" : EVP_MD_name(md));
+#endif
+ if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+#ifndef OPENSSL_NO_GOST
+ {
+ int pktype = EVP_PKEY_id(pkey);
+ if (pktype == NID_id_GostR3410_2001
+ || pktype == NID_id_GostR3410_2012_256
+ || pktype == NID_id_GostR3410_2012_512) {
+ if ((gost_data = OPENSSL_malloc(len)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ BUF_reverse(gost_data, data, len);
+ data = gost_data;
+ }
+ }
+#endif
+
+ if (SSL_USE_PSS(s)) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
+ || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
+ RSA_PSS_SALTLEN_DIGEST) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ }
+ if (s->version == SSL3_VERSION) {
+ if (EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0
+ || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
+ (int)s->session->master_key_length,
+ s->session->master_key)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_BAD_SIGNATURE);
+ goto err;
+ }
+ } else {
+ j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
+ if (j <= 0) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+ SSL_R_BAD_SIGNATURE);
+ goto err;
+ }
+ }
+
+ /*
+ * In TLSv1.3 on the client side we make sure we prepare the client
+ * certificate after the CertVerify instead of when we get the
+ * CertificateRequest. This is because in TLSv1.3 the CertificateRequest
+ * comes *before* the Certificate message. In TLSv1.2 it comes after. We
+ * want to make sure that SSL_get_peer_certificate() will return the actual
+ * server certificate from the client_cert_cb callback.
+ */
+ if (!s->server && SSL_IS_TLS13(s) && s->s3->tmp.cert_req == 1)
+ ret = MSG_PROCESS_CONTINUE_PROCESSING;
+ else
+ ret = MSG_PROCESS_CONTINUE_READING;
+ err:
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
+ EVP_MD_CTX_free(mctx);
+#ifndef OPENSSL_NO_GOST
+ OPENSSL_free(gost_data);
+#endif
+ return ret;
+}
+
+int tls_construct_finished(SSL *s, WPACKET *pkt)
+{
+ size_t finish_md_len;
+ const char *sender;
+ size_t slen;
+
+ /* This is a real handshake so make sure we clean it up at the end */
+ if (!s->server && s->post_handshake_auth != SSL_PHA_REQUESTED)
+ s->statem.cleanuphand = 1;
+
+ /*
+ * We only change the keys if we didn't already do this when we sent the
+ * client certificate
+ */
+ if (SSL_IS_TLS13(s)
+ && !s->server
+ && s->s3->tmp.cert_req == 0
+ && (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {;
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ if (s->server) {
+ sender = s->method->ssl3_enc->server_finished_label;
+ slen = s->method->ssl3_enc->server_finished_label_len;
+ } else {
+ sender = s->method->ssl3_enc->client_finished_label;
+ slen = s->method->ssl3_enc->client_finished_label_len;
+ }
+
+ finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
+ sender, slen,
+ s->s3->tmp.finish_md);
+ if (finish_md_len == 0) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ s->s3->tmp.finish_md_len = finish_md_len;
+
+ if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*
+ * Log the master secret, if logging is enabled. We don't log it for
+ * TLSv1.3: there's a different key schedule for that.
+ */
+ if (!SSL_IS_TLS13(s) && !ssl_log_secret(s, MASTER_SECRET_LABEL,
+ s->session->master_key,
+ s->session->master_key_length)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ /*
+ * Copy the finished so we can use it for renegotiation checks
+ */
+ if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!s->server) {
+ memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md,
+ finish_md_len);
+ s->s3->previous_client_finished_len = finish_md_len;
+ } else {
+ memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md,
+ finish_md_len);
+ s->s3->previous_server_finished_len = finish_md_len;
+ }
+
+ return 1;
+}
+
+int tls_construct_key_update(SSL *s, WPACKET *pkt)
+{
+ if (!WPACKET_put_bytes_u8(pkt, s->key_update)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ s->key_update = SSL_KEY_UPDATE_NONE;
+ return 1;
+}
+
+MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
+{
+ unsigned int updatetype;
+
+ /*
+ * A KeyUpdate message signals a key change so the end of the message must
+ * be on a record boundary.
+ */
+ if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE,
+ SSL_R_NOT_ON_RECORD_BOUNDARY);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (!PACKET_get_1(pkt, &updatetype)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE,
+ SSL_R_BAD_KEY_UPDATE);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /*
+ * There are only two defined key update types. Fail if we get a value we
+ * didn't recognise.
+ */
+ if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
+ && updatetype != SSL_KEY_UPDATE_REQUESTED) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
+ SSL_R_BAD_KEY_UPDATE);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /*
+ * If we get a request for us to update our sending keys too then, we need
+ * to additionally send a KeyUpdate message. However that message should
* not also request an update (otherwise we get into an infinite loop).
- */
+ */
if (updatetype == SSL_KEY_UPDATE_REQUESTED)
- s->key_update = SSL_KEY_UPDATE_NOT_REQUESTED;
-
- if (!tls13_update_key(s, 0)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
-
- return MSG_PROCESS_FINISHED_READING;
-}
-
-/*
- * ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
- * to far.
- */
-int ssl3_take_mac(SSL *s)
-{
- const char *sender;
- size_t slen;
-
- if (!s->server) {
- sender = s->method->ssl3_enc->server_finished_label;
- slen = s->method->ssl3_enc->server_finished_label_len;
- } else {
- sender = s->method->ssl3_enc->client_finished_label;
- slen = s->method->ssl3_enc->client_finished_label_len;
- }
-
- s->s3->tmp.peer_finish_md_len =
- s->method->ssl3_enc->final_finish_mac(s, sender, slen,
- s->s3->tmp.peer_finish_md);
-
- if (s->s3->tmp.peer_finish_md_len == 0) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
-{
- size_t remain;
-
- remain = PACKET_remaining(pkt);
- /*
- * 'Change Cipher Spec' is just a single byte, which should already have
- * been consumed by ssl_get_message() so there should be no bytes left,
- * unless we're using DTLS1_BAD_VER, which has an extra 2 bytes
- */
- if (SSL_IS_DTLS(s)) {
- if ((s->version == DTLS1_BAD_VER
- && remain != DTLS1_CCS_HEADER_LENGTH + 1)
- || (s->version != DTLS1_BAD_VER
- && remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
- SSL_R_BAD_CHANGE_CIPHER_SPEC);
- return MSG_PROCESS_ERROR;
- }
- } else {
- if (remain != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
- SSL_R_BAD_CHANGE_CIPHER_SPEC);
- return MSG_PROCESS_ERROR;
- }
- }
-
- /* Check we have a cipher to change to */
- if (s->s3->tmp.new_cipher == NULL) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
- return MSG_PROCESS_ERROR;
- }
-
- s->s3->change_cipher_spec = 1;
- if (!ssl3_do_change_cipher_spec(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
- ERR_R_INTERNAL_ERROR);
- return MSG_PROCESS_ERROR;
- }
-
- if (SSL_IS_DTLS(s)) {
- dtls1_reset_seq_numbers(s, SSL3_CC_READ);
-
- if (s->version == DTLS1_BAD_VER)
- s->d1->handshake_read_seq++;
-
-#ifndef OPENSSL_NO_SCTP
- /*
- * Remember that a CCS has been received, so that an old key of
- * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no
- * SCTP is used
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
-#endif
- }
-
- return MSG_PROCESS_CONTINUE_READING;
-}
-
-MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
-{
- size_t md_len;
-
-
- /* This is a real handshake so make sure we clean it up at the end */
- if (s->server) {
- /*
- * To get this far we must have read encrypted data from the client. We
- * no longer tolerate unencrypted alerts. This value is ignored if less
- * than TLSv1.3
- */
- s->statem.enc_read_state = ENC_READ_STATE_VALID;
- if (s->post_handshake_auth != SSL_PHA_REQUESTED)
- s->statem.cleanuphand = 1;
- if (SSL_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
- }
-
- /*
- * In TLSv1.3 a Finished message signals a key change so the end of the
- * message must be on a record boundary.
- */
- if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
- return MSG_PROCESS_ERROR;
- }
-
- /* If this occurs, we have missed a message */
- if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_GOT_A_FIN_BEFORE_A_CCS);
- return MSG_PROCESS_ERROR;
- }
- s->s3->change_cipher_spec = 0;
-
- md_len = s->s3->tmp.peer_finish_md_len;
-
- if (md_len != PACKET_remaining(pkt)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_BAD_DIGEST_LENGTH);
- return MSG_PROCESS_ERROR;
- }
-
- if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md,
- md_len) != 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED,
- SSL_R_DIGEST_CHECK_FAILED);
- return MSG_PROCESS_ERROR;
- }
-
- /*
- * Copy the finished so we can use it for renegotiation checks
- */
- if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED,
- ERR_R_INTERNAL_ERROR);
- return MSG_PROCESS_ERROR;
- }
- if (s->server) {
- memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md,
- md_len);
- s->s3->previous_client_finished_len = md_len;
- } else {
- memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md,
- md_len);
- s->s3->previous_server_finished_len = md_len;
- }
-
- /*
- * In TLS1.3 we also have to change cipher state and do any final processing
- * of the initial server flight (if we are a client)
- */
- if (SSL_IS_TLS13(s)) {
- if (s->server) {
- if (s->post_handshake_auth != SSL_PHA_REQUESTED &&
- !s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
- } else {
+ s->key_update = SSL_KEY_UPDATE_NOT_REQUESTED;
+
+ if (!tls13_update_key(s, 0)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+
+ return MSG_PROCESS_FINISHED_READING;
+}
+
+/*
+ * ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
+ * to far.
+ */
+int ssl3_take_mac(SSL *s)
+{
+ const char *sender;
+ size_t slen;
+
+ if (!s->server) {
+ sender = s->method->ssl3_enc->server_finished_label;
+ slen = s->method->ssl3_enc->server_finished_label_len;
+ } else {
+ sender = s->method->ssl3_enc->client_finished_label;
+ slen = s->method->ssl3_enc->client_finished_label_len;
+ }
+
+ s->s3->tmp.peer_finish_md_len =
+ s->method->ssl3_enc->final_finish_mac(s, sender, slen,
+ s->s3->tmp.peer_finish_md);
+
+ if (s->s3->tmp.peer_finish_md_len == 0) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
+{
+ size_t remain;
+
+ remain = PACKET_remaining(pkt);
+ /*
+ * 'Change Cipher Spec' is just a single byte, which should already have
+ * been consumed by ssl_get_message() so there should be no bytes left,
+ * unless we're using DTLS1_BAD_VER, which has an extra 2 bytes
+ */
+ if (SSL_IS_DTLS(s)) {
+ if ((s->version == DTLS1_BAD_VER
+ && remain != DTLS1_CCS_HEADER_LENGTH + 1)
+ || (s->version != DTLS1_BAD_VER
+ && remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ return MSG_PROCESS_ERROR;
+ }
+ } else {
+ if (remain != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ return MSG_PROCESS_ERROR;
+ }
+ }
+
+ /* Check we have a cipher to change to */
+ if (s->s3->tmp.new_cipher == NULL) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
+ return MSG_PROCESS_ERROR;
+ }
+
+ s->s3->change_cipher_spec = 1;
+ if (!ssl3_do_change_cipher_spec(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+ ERR_R_INTERNAL_ERROR);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ dtls1_reset_seq_numbers(s, SSL3_CC_READ);
+
+ if (s->version == DTLS1_BAD_VER)
+ s->d1->handshake_read_seq++;
+
+#ifndef OPENSSL_NO_SCTP
+ /*
+ * Remember that a CCS has been received, so that an old key of
+ * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no
+ * SCTP is used
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
+#endif
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+}
+
+MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
+{
+ size_t md_len;
+
+
+ /* This is a real handshake so make sure we clean it up at the end */
+ if (s->server) {
+ /*
+ * To get this far we must have read encrypted data from the client. We
+ * no longer tolerate unencrypted alerts. This value is ignored if less
+ * than TLSv1.3
+ */
+ s->statem.enc_read_state = ENC_READ_STATE_VALID;
+ if (s->post_handshake_auth != SSL_PHA_REQUESTED)
+ s->statem.cleanuphand = 1;
+ if (SSL_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+ }
+
+ /*
+ * In TLSv1.3 a Finished message signals a key change so the end of the
+ * message must be on a record boundary.
+ */
+ if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
+ SSL_R_NOT_ON_RECORD_BOUNDARY);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /* If this occurs, we have missed a message */
+ if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
+ SSL_R_GOT_A_FIN_BEFORE_A_CCS);
+ return MSG_PROCESS_ERROR;
+ }
+ s->s3->change_cipher_spec = 0;
+
+ md_len = s->s3->tmp.peer_finish_md_len;
+
+ if (md_len != PACKET_remaining(pkt)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED,
+ SSL_R_BAD_DIGEST_LENGTH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md,
+ md_len) != 0) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED,
+ SSL_R_DIGEST_CHECK_FAILED);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /*
+ * Copy the finished so we can use it for renegotiation checks
+ */
+ if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED,
+ ERR_R_INTERNAL_ERROR);
+ return MSG_PROCESS_ERROR;
+ }
+ if (s->server) {
+ memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md,
+ md_len);
+ s->s3->previous_client_finished_len = md_len;
+ } else {
+ memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md,
+ md_len);
+ s->s3->previous_server_finished_len = md_len;
+ }
+
+ /*
+ * In TLS1.3 we also have to change cipher state and do any final processing
+ * of the initial server flight (if we are a client)
+ */
+ if (SSL_IS_TLS13(s)) {
+ if (s->server) {
+ if (s->post_handshake_auth != SSL_PHA_REQUESTED &&
+ !s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+ } else {
/* TLS 1.3 gets the secret size from the handshake md */
size_t dummy;
- if (!s->method->ssl3_enc->generate_master_secret(s,
- s->master_secret, s->handshake_secret, 0,
+ if (!s->method->ssl3_enc->generate_master_secret(s,
+ s->master_secret, s->handshake_secret, 0,
&dummy)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
- if (!tls_process_initial_server_flight(s)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
- }
- }
-
- return MSG_PROCESS_FINISHED_READING;
-}
-
-int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
-{
- if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-/* Add a certificate to the WPACKET */
-static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain)
-{
- int len;
- unsigned char *outbytes;
-
- len = i2d_X509(x, NULL);
- if (len < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
- ERR_R_BUF_LIB);
- return 0;
- }
- if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
- || i2d_X509(x, &outbytes) != len) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (SSL_IS_TLS13(s)
- && !tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_CERTIFICATE, x,
- chain)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-/* Add certificate chain to provided WPACKET */
-static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
-{
- int i, chain_count;
- X509 *x;
- STACK_OF(X509) *extra_certs;
- STACK_OF(X509) *chain = NULL;
- X509_STORE *chain_store;
-
- if (cpk == NULL || cpk->x509 == NULL)
- return 1;
-
- x = cpk->x509;
-
- /*
- * If we have a certificate specific chain use it, else use parent ctx.
- */
- if (cpk->chain != NULL)
- extra_certs = cpk->chain;
- else
- extra_certs = s->ctx->extra_certs;
-
- if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
- chain_store = NULL;
- else if (s->cert->chain_store)
- chain_store = s->cert->chain_store;
- else
- chain_store = s->ctx->cert_store;
-
- if (chain_store != NULL) {
- X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
-
- if (xs_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
- X509_STORE_CTX_free(xs_ctx);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
- ERR_R_X509_LIB);
- return 0;
- }
- /*
- * It is valid for the chain not to be complete (because normally we
- * don't include the root cert in the chain). Therefore we deliberately
- * ignore the error return from this call. We're not actually verifying
- * the cert - we're just building as much of the chain as we can
- */
- (void)X509_verify_cert(xs_ctx);
- /* Don't leave errors in the queue */
- ERR_clear_error();
- chain = X509_STORE_CTX_get0_chain(xs_ctx);
- i = ssl_security_cert_chain(s, chain, NULL, 0);
- if (i != 1) {
-#if 0
- /* Dummy error calls so mkerr generates them */
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
- SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
-#endif
- X509_STORE_CTX_free(xs_ctx);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
- return 0;
- }
- chain_count = sk_X509_num(chain);
- for (i = 0; i < chain_count; i++) {
- x = sk_X509_value(chain, i);
-
- if (!ssl_add_cert_to_wpacket(s, pkt, x, i)) {
- /* SSLfatal() already called */
- X509_STORE_CTX_free(xs_ctx);
- return 0;
- }
- }
- X509_STORE_CTX_free(xs_ctx);
- } else {
- i = ssl_security_cert_chain(s, extra_certs, x, 0);
- if (i != 1) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
- return 0;
- }
- if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
- for (i = 0; i < sk_X509_num(extra_certs); i++) {
- x = sk_X509_value(extra_certs, i);
- if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
- }
- return 1;
-}
-
-unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
-{
- if (!WPACKET_start_sub_packet_u24(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!ssl_add_cert_chain(s, pkt, cpk))
- return 0;
-
- if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Tidy up after the end of a handshake. In the case of SCTP this may result
- * in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
- * freed up as well.
- */
-WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
-{
- void (*cb) (const SSL *ssl, int type, int val) = NULL;
- int cleanuphand = s->statem.cleanuphand;
-
- if (clearbufs) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+ if (!tls_process_initial_server_flight(s)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+ }
+ }
+
+ return MSG_PROCESS_FINISHED_READING;
+}
+
+int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
+{
+ if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Add a certificate to the WPACKET */
+static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain)
+{
+ int len;
+ unsigned char *outbytes;
+
+ len = i2d_X509(x, NULL);
+ if (len < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
+ ERR_R_BUF_LIB);
+ return 0;
+ }
+ if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
+ || i2d_X509(x, &outbytes) != len) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (SSL_IS_TLS13(s)
+ && !tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_CERTIFICATE, x,
+ chain)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Add certificate chain to provided WPACKET */
+static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
+{
+ int i, chain_count;
+ X509 *x;
+ STACK_OF(X509) *extra_certs;
+ STACK_OF(X509) *chain = NULL;
+ X509_STORE *chain_store;
+
+ if (cpk == NULL || cpk->x509 == NULL)
+ return 1;
+
+ x = cpk->x509;
+
+ /*
+ * If we have a certificate specific chain use it, else use parent ctx.
+ */
+ if (cpk->chain != NULL)
+ extra_certs = cpk->chain;
+ else
+ extra_certs = s->ctx->extra_certs;
+
+ if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
+ chain_store = NULL;
+ else if (s->cert->chain_store)
+ chain_store = s->cert->chain_store;
+ else
+ chain_store = s->ctx->cert_store;
+
+ if (chain_store != NULL) {
+ X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
+
+ if (xs_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
+ X509_STORE_CTX_free(xs_ctx);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
+ ERR_R_X509_LIB);
+ return 0;
+ }
+ /*
+ * It is valid for the chain not to be complete (because normally we
+ * don't include the root cert in the chain). Therefore we deliberately
+ * ignore the error return from this call. We're not actually verifying
+ * the cert - we're just building as much of the chain as we can
+ */
+ (void)X509_verify_cert(xs_ctx);
+ /* Don't leave errors in the queue */
+ ERR_clear_error();
+ chain = X509_STORE_CTX_get0_chain(xs_ctx);
+ i = ssl_security_cert_chain(s, chain, NULL, 0);
+ if (i != 1) {
+#if 0
+ /* Dummy error calls so mkerr generates them */
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
+#endif
+ X509_STORE_CTX_free(xs_ctx);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
+ return 0;
+ }
+ chain_count = sk_X509_num(chain);
+ for (i = 0; i < chain_count; i++) {
+ x = sk_X509_value(chain, i);
+
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, i)) {
+ /* SSLfatal() already called */
+ X509_STORE_CTX_free(xs_ctx);
+ return 0;
+ }
+ }
+ X509_STORE_CTX_free(xs_ctx);
+ } else {
+ i = ssl_security_cert_chain(s, extra_certs, x, 0);
+ if (i != 1) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
+ return 0;
+ }
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ for (i = 0; i < sk_X509_num(extra_certs); i++) {
+ x = sk_X509_value(extra_certs, i);
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
+{
+ if (!WPACKET_start_sub_packet_u24(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!ssl_add_cert_chain(s, pkt, cpk))
+ return 0;
+
+ if (!WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Tidy up after the end of a handshake. In the case of SCTP this may result
+ * in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
+ * freed up as well.
+ */
+WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
+{
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+ int cleanuphand = s->statem.cleanuphand;
+
+ if (clearbufs) {
if (!SSL_IS_DTLS(s)
#ifndef OPENSSL_NO_SCTP
- /*
+ /*
* RFC6083: SCTP provides a reliable and in-sequence transport service for DTLS
* messages that require it. Therefore, DTLS procedures for retransmissions
* MUST NOT be used.
@@ -1048,473 +1048,473 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
) {
/*
* We don't do this in DTLS over UDP because we may still need the init_buf
- * in case there are any unexpected retransmits
- */
- BUF_MEM_free(s->init_buf);
- s->init_buf = NULL;
- }
-
- if (!ssl_free_wbio_buffer(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
- }
- s->init_num = 0;
- }
-
- if (SSL_IS_TLS13(s) && !s->server
- && s->post_handshake_auth == SSL_PHA_REQUESTED)
- s->post_handshake_auth = SSL_PHA_EXT_SENT;
-
- /*
- * Only set if there was a Finished message and this isn't after a TLSv1.3
- * post handshake exchange
- */
- if (cleanuphand) {
- /* skipped if we just sent a HelloRequest */
- s->renegotiate = 0;
- s->new_session = 0;
- s->statem.cleanuphand = 0;
- s->ext.ticket_expected = 0;
-
- ssl3_cleanup_key_block(s);
-
- if (s->server) {
- /*
- * In TLSv1.3 we update the cache as part of constructing the
- * NewSessionTicket
- */
- if (!SSL_IS_TLS13(s))
- ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
-
- /* N.B. s->ctx may not equal s->session_ctx */
- tsan_counter(&s->ctx->stats.sess_accept_good);
- s->handshake_func = ossl_statem_accept;
- } else {
- if (SSL_IS_TLS13(s)) {
- /*
- * We encourage applications to only use TLSv1.3 tickets once,
- * so we remove this one from the cache.
- */
- if ((s->session_ctx->session_cache_mode
- & SSL_SESS_CACHE_CLIENT) != 0)
- SSL_CTX_remove_session(s->session_ctx, s->session);
- } else {
- /*
- * In TLSv1.3 we update the cache as part of processing the
- * NewSessionTicket
- */
- ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
- }
- if (s->hit)
- tsan_counter(&s->session_ctx->stats.sess_hit);
-
- s->handshake_func = ossl_statem_connect;
- tsan_counter(&s->session_ctx->stats.sess_connect_good);
- }
-
- if (SSL_IS_DTLS(s)) {
- /* done with handshaking */
- s->d1->handshake_read_seq = 0;
- s->d1->handshake_write_seq = 0;
- s->d1->next_handshake_write_seq = 0;
- dtls1_clear_received_buffer(s);
- }
- }
-
- if (s->info_callback != NULL)
- cb = s->info_callback;
- else if (s->ctx->info_callback != NULL)
- cb = s->ctx->info_callback;
-
- /* The callback may expect us to not be in init at handshake done */
- ossl_statem_set_in_init(s, 0);
-
- if (cb != NULL) {
- if (cleanuphand
- || !SSL_IS_TLS13(s)
- || SSL_IS_FIRST_HANDSHAKE(s))
- cb(s, SSL_CB_HANDSHAKE_DONE, 1);
- }
-
- if (!stop) {
- /* If we've got more work to do we go back into init */
- ossl_statem_set_in_init(s, 1);
- return WORK_FINISHED_CONTINUE;
- }
-
- return WORK_FINISHED_STOP;
-}
-
-int tls_get_message_header(SSL *s, int *mt)
-{
- /* s->init_num < SSL3_HM_HEADER_LENGTH */
- int skip_message, i, recvd_type;
- unsigned char *p;
- size_t l, readbytes;
-
- p = (unsigned char *)s->init_buf->data;
-
- do {
- while (s->init_num < SSL3_HM_HEADER_LENGTH) {
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
- &p[s->init_num],
- SSL3_HM_HEADER_LENGTH - s->init_num,
- 0, &readbytes);
- if (i <= 0) {
- s->rwstate = SSL_READING;
- return 0;
- }
- if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
- /*
- * A ChangeCipherSpec must be a single byte and may not occur
- * in the middle of a handshake message.
- */
- if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_GET_MESSAGE_HEADER,
- SSL_R_BAD_CHANGE_CIPHER_SPEC);
- return 0;
- }
- if (s->statem.hand_state == TLS_ST_BEFORE
- && (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) {
- /*
- * We are stateless and we received a CCS. Probably this is
- * from a client between the first and second ClientHellos.
- * We should ignore this, but return an error because we do
- * not return success until we see the second ClientHello
- * with a valid cookie.
- */
- return 0;
- }
- s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
- s->init_num = readbytes - 1;
- s->init_msg = s->init_buf->data;
- s->s3->tmp.message_size = readbytes;
- return 1;
- } else if (recvd_type != SSL3_RT_HANDSHAKE) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_GET_MESSAGE_HEADER,
- SSL_R_CCS_RECEIVED_EARLY);
- return 0;
- }
- s->init_num += readbytes;
- }
-
- skip_message = 0;
- if (!s->server)
- if (s->statem.hand_state != TLS_ST_OK
- && p[0] == SSL3_MT_HELLO_REQUEST)
- /*
- * The server may always send 'Hello Request' messages --
- * we are doing a handshake anyway now, so ignore them if
- * their format is correct. Does not count for 'Finished'
- * MAC.
- */
- if (p[1] == 0 && p[2] == 0 && p[3] == 0) {
- s->init_num = 0;
- skip_message = 1;
-
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- p, SSL3_HM_HEADER_LENGTH, s,
- s->msg_callback_arg);
- }
- } while (skip_message);
- /* s->init_num == SSL3_HM_HEADER_LENGTH */
-
- *mt = *p;
- s->s3->tmp.message_type = *(p++);
-
- if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
- /*
- * Only happens with SSLv3+ in an SSLv2 backward compatible
- * ClientHello
- *
- * Total message size is the remaining record bytes to read
- * plus the SSL3_HM_HEADER_LENGTH bytes that we already read
- */
- l = RECORD_LAYER_get_rrec_length(&s->rlayer)
- + SSL3_HM_HEADER_LENGTH;
- s->s3->tmp.message_size = l;
-
- s->init_msg = s->init_buf->data;
- s->init_num = SSL3_HM_HEADER_LENGTH;
- } else {
- n2l3(p, l);
- /* BUF_MEM_grow takes an 'int' parameter */
- if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER,
- SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return 0;
- }
- s->s3->tmp.message_size = l;
-
- s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
- s->init_num = 0;
- }
-
- return 1;
-}
-
-int tls_get_message_body(SSL *s, size_t *len)
-{
- size_t n, readbytes;
- unsigned char *p;
- int i;
-
- if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) {
- /* We've already read everything in */
- *len = (unsigned long)s->init_num;
- return 1;
- }
-
- p = s->init_msg;
- n = s->s3->tmp.message_size - s->init_num;
- while (n > 0) {
- i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
- &p[s->init_num], n, 0, &readbytes);
- if (i <= 0) {
- s->rwstate = SSL_READING;
- *len = 0;
- return 0;
- }
- s->init_num += readbytes;
- n -= readbytes;
- }
-
- /*
- * If receiving Finished, record MAC of prior handshake messages for
- * Finished verification.
- */
- if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
- /* SSLfatal() already called */
- *len = 0;
- return 0;
- }
-
- /* Feed this message into MAC computation. */
- if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
- if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->init_num)) {
- /* SSLfatal() already called */
- *len = 0;
- return 0;
- }
- if (s->msg_callback)
- s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data,
- (size_t)s->init_num, s, s->msg_callback_arg);
- } else {
- /*
- * We defer feeding in the HRR until later. We'll do it as part of
- * processing the message
- * The TLsv1.3 handshake transcript stops at the ClientFinished
- * message.
- */
-#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
- /* KeyUpdate and NewSessionTicket do not need to be added */
- if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET
- && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) {
- if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
- || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
- || memcmp(hrrrandom,
- s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
- SSL3_RANDOM_SIZE) != 0) {
- if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->init_num + SSL3_HM_HEADER_LENGTH)) {
- /* SSLfatal() already called */
- *len = 0;
- return 0;
- }
- }
- }
- if (s->msg_callback)
- s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
- (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s,
- s->msg_callback_arg);
- }
-
- *len = s->init_num;
- return 1;
-}
-
-static const X509ERR2ALERT x509table[] = {
- {X509_V_ERR_APPLICATION_VERIFICATION, SSL_AD_HANDSHAKE_FAILURE},
- {X509_V_ERR_CA_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE},
+ * in case there are any unexpected retransmits
+ */
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+ }
+
+ if (!ssl_free_wbio_buffer(s)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+ }
+ s->init_num = 0;
+ }
+
+ if (SSL_IS_TLS13(s) && !s->server
+ && s->post_handshake_auth == SSL_PHA_REQUESTED)
+ s->post_handshake_auth = SSL_PHA_EXT_SENT;
+
+ /*
+ * Only set if there was a Finished message and this isn't after a TLSv1.3
+ * post handshake exchange
+ */
+ if (cleanuphand) {
+ /* skipped if we just sent a HelloRequest */
+ s->renegotiate = 0;
+ s->new_session = 0;
+ s->statem.cleanuphand = 0;
+ s->ext.ticket_expected = 0;
+
+ ssl3_cleanup_key_block(s);
+
+ if (s->server) {
+ /*
+ * In TLSv1.3 we update the cache as part of constructing the
+ * NewSessionTicket
+ */
+ if (!SSL_IS_TLS13(s))
+ ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
+
+ /* N.B. s->ctx may not equal s->session_ctx */
+ tsan_counter(&s->ctx->stats.sess_accept_good);
+ s->handshake_func = ossl_statem_accept;
+ } else {
+ if (SSL_IS_TLS13(s)) {
+ /*
+ * We encourage applications to only use TLSv1.3 tickets once,
+ * so we remove this one from the cache.
+ */
+ if ((s->session_ctx->session_cache_mode
+ & SSL_SESS_CACHE_CLIENT) != 0)
+ SSL_CTX_remove_session(s->session_ctx, s->session);
+ } else {
+ /*
+ * In TLSv1.3 we update the cache as part of processing the
+ * NewSessionTicket
+ */
+ ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
+ }
+ if (s->hit)
+ tsan_counter(&s->session_ctx->stats.sess_hit);
+
+ s->handshake_func = ossl_statem_connect;
+ tsan_counter(&s->session_ctx->stats.sess_connect_good);
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ /* done with handshaking */
+ s->d1->handshake_read_seq = 0;
+ s->d1->handshake_write_seq = 0;
+ s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
+ }
+ }
+
+ if (s->info_callback != NULL)
+ cb = s->info_callback;
+ else if (s->ctx->info_callback != NULL)
+ cb = s->ctx->info_callback;
+
+ /* The callback may expect us to not be in init at handshake done */
+ ossl_statem_set_in_init(s, 0);
+
+ if (cb != NULL) {
+ if (cleanuphand
+ || !SSL_IS_TLS13(s)
+ || SSL_IS_FIRST_HANDSHAKE(s))
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+ }
+
+ if (!stop) {
+ /* If we've got more work to do we go back into init */
+ ossl_statem_set_in_init(s, 1);
+ return WORK_FINISHED_CONTINUE;
+ }
+
+ return WORK_FINISHED_STOP;
+}
+
+int tls_get_message_header(SSL *s, int *mt)
+{
+ /* s->init_num < SSL3_HM_HEADER_LENGTH */
+ int skip_message, i, recvd_type;
+ unsigned char *p;
+ size_t l, readbytes;
+
+ p = (unsigned char *)s->init_buf->data;
+
+ do {
+ while (s->init_num < SSL3_HM_HEADER_LENGTH) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
+ &p[s->init_num],
+ SSL3_HM_HEADER_LENGTH - s->init_num,
+ 0, &readbytes);
+ if (i <= 0) {
+ s->rwstate = SSL_READING;
+ return 0;
+ }
+ if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+ /*
+ * A ChangeCipherSpec must be a single byte and may not occur
+ * in the middle of a handshake message.
+ */
+ if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_GET_MESSAGE_HEADER,
+ SSL_R_BAD_CHANGE_CIPHER_SPEC);
+ return 0;
+ }
+ if (s->statem.hand_state == TLS_ST_BEFORE
+ && (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) {
+ /*
+ * We are stateless and we received a CCS. Probably this is
+ * from a client between the first and second ClientHellos.
+ * We should ignore this, but return an error because we do
+ * not return success until we see the second ClientHello
+ * with a valid cookie.
+ */
+ return 0;
+ }
+ s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
+ s->init_num = readbytes - 1;
+ s->init_msg = s->init_buf->data;
+ s->s3->tmp.message_size = readbytes;
+ return 1;
+ } else if (recvd_type != SSL3_RT_HANDSHAKE) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_GET_MESSAGE_HEADER,
+ SSL_R_CCS_RECEIVED_EARLY);
+ return 0;
+ }
+ s->init_num += readbytes;
+ }
+
+ skip_message = 0;
+ if (!s->server)
+ if (s->statem.hand_state != TLS_ST_OK
+ && p[0] == SSL3_MT_HELLO_REQUEST)
+ /*
+ * The server may always send 'Hello Request' messages --
+ * we are doing a handshake anyway now, so ignore them if
+ * their format is correct. Does not count for 'Finished'
+ * MAC.
+ */
+ if (p[1] == 0 && p[2] == 0 && p[3] == 0) {
+ s->init_num = 0;
+ skip_message = 1;
+
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+ p, SSL3_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
+ }
+ } while (skip_message);
+ /* s->init_num == SSL3_HM_HEADER_LENGTH */
+
+ *mt = *p;
+ s->s3->tmp.message_type = *(p++);
+
+ if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
+ /*
+ * Only happens with SSLv3+ in an SSLv2 backward compatible
+ * ClientHello
+ *
+ * Total message size is the remaining record bytes to read
+ * plus the SSL3_HM_HEADER_LENGTH bytes that we already read
+ */
+ l = RECORD_LAYER_get_rrec_length(&s->rlayer)
+ + SSL3_HM_HEADER_LENGTH;
+ s->s3->tmp.message_size = l;
+
+ s->init_msg = s->init_buf->data;
+ s->init_num = SSL3_HM_HEADER_LENGTH;
+ } else {
+ n2l3(p, l);
+ /* BUF_MEM_grow takes an 'int' parameter */
+ if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER,
+ SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return 0;
+ }
+ s->s3->tmp.message_size = l;
+
+ s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
+ s->init_num = 0;
+ }
+
+ return 1;
+}
+
+int tls_get_message_body(SSL *s, size_t *len)
+{
+ size_t n, readbytes;
+ unsigned char *p;
+ int i;
+
+ if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ /* We've already read everything in */
+ *len = (unsigned long)s->init_num;
+ return 1;
+ }
+
+ p = s->init_msg;
+ n = s->s3->tmp.message_size - s->init_num;
+ while (n > 0) {
+ i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
+ &p[s->init_num], n, 0, &readbytes);
+ if (i <= 0) {
+ s->rwstate = SSL_READING;
+ *len = 0;
+ return 0;
+ }
+ s->init_num += readbytes;
+ n -= readbytes;
+ }
+
+ /*
+ * If receiving Finished, record MAC of prior handshake messages for
+ * Finished verification.
+ */
+ if (*(s->init_buf->data) == SSL3_MT_FINISHED && !ssl3_take_mac(s)) {
+ /* SSLfatal() already called */
+ *len = 0;
+ return 0;
+ }
+
+ /* Feed this message into MAC computation. */
+ if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num)) {
+ /* SSLfatal() already called */
+ *len = 0;
+ return 0;
+ }
+ if (s->msg_callback)
+ s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data,
+ (size_t)s->init_num, s, s->msg_callback_arg);
+ } else {
+ /*
+ * We defer feeding in the HRR until later. We'll do it as part of
+ * processing the message
+ * The TLsv1.3 handshake transcript stops at the ClientFinished
+ * message.
+ */
+#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
+ /* KeyUpdate and NewSessionTicket do not need to be added */
+ if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET
+ && s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) {
+ if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
+ || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
+ || memcmp(hrrrandom,
+ s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
+ SSL3_RANDOM_SIZE) != 0) {
+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num + SSL3_HM_HEADER_LENGTH)) {
+ /* SSLfatal() already called */
+ *len = 0;
+ return 0;
+ }
+ }
+ }
+ if (s->msg_callback)
+ s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
+ (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
+ }
+
+ *len = s->init_num;
+ return 1;
+}
+
+static const X509ERR2ALERT x509table[] = {
+ {X509_V_ERR_APPLICATION_VERIFICATION, SSL_AD_HANDSHAKE_FAILURE},
+ {X509_V_ERR_CA_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE},
{X509_V_ERR_EC_KEY_EXPLICIT_PARAMS, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_CA_MD_TOO_WEAK, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_CERT_CHAIN_TOO_LONG, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_CERT_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED},
- {X509_V_ERR_CERT_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_CERT_REJECTED, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_CERT_REVOKED, SSL_AD_CERTIFICATE_REVOKED},
- {X509_V_ERR_CERT_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR},
- {X509_V_ERR_CERT_UNTRUSTED, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_CRL_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED},
- {X509_V_ERR_CRL_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_CRL_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR},
- {X509_V_ERR_DANE_NO_MATCH, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_EE_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_EMAIL_MISMATCH, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_HOSTNAME_MISMATCH, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_INVALID_CA, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_INVALID_CALL, SSL_AD_INTERNAL_ERROR},
- {X509_V_ERR_INVALID_PURPOSE, SSL_AD_UNSUPPORTED_CERTIFICATE},
- {X509_V_ERR_IP_ADDRESS_MISMATCH, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_OUT_OF_MEM, SSL_AD_INTERNAL_ERROR},
- {X509_V_ERR_PATH_LENGTH_EXCEEDED, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_STORE_LOOKUP, SSL_AD_INTERNAL_ERROR},
- {X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, SSL_AD_BAD_CERTIFICATE},
- {X509_V_ERR_UNABLE_TO_GET_CRL, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, SSL_AD_UNKNOWN_CA},
- {X509_V_ERR_UNSPECIFIED, SSL_AD_INTERNAL_ERROR},
-
- /* Last entry; return this if we don't find the value above. */
- {X509_V_OK, SSL_AD_CERTIFICATE_UNKNOWN}
-};
-
-int ssl_x509err2alert(int x509err)
-{
- const X509ERR2ALERT *tp;
-
- for (tp = x509table; tp->x509err != X509_V_OK; ++tp)
- if (tp->x509err == x509err)
- break;
- return tp->alert;
-}
-
-int ssl_allow_compression(SSL *s)
-{
- if (s->options & SSL_OP_NO_COMPRESSION)
- return 0;
- return ssl_security(s, SSL_SECOP_COMPRESSION, 0, 0, NULL);
-}
-
-static int version_cmp(const SSL *s, int a, int b)
-{
- int dtls = SSL_IS_DTLS(s);
-
- if (a == b)
- return 0;
- if (!dtls)
- return a < b ? -1 : 1;
- return DTLS_VERSION_LT(a, b) ? -1 : 1;
-}
-
-typedef struct {
- int version;
- const SSL_METHOD *(*cmeth) (void);
- const SSL_METHOD *(*smeth) (void);
-} version_info;
-
-#if TLS_MAX_VERSION != TLS1_3_VERSION
-# error Code needs update for TLS_method() support beyond TLS1_3_VERSION.
-#endif
-
-/* Must be in order high to low */
-static const version_info tls_version_table[] = {
-#ifndef OPENSSL_NO_TLS1_3
- {TLS1_3_VERSION, tlsv1_3_client_method, tlsv1_3_server_method},
-#else
- {TLS1_3_VERSION, NULL, NULL},
-#endif
-#ifndef OPENSSL_NO_TLS1_2
- {TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method},
-#else
- {TLS1_2_VERSION, NULL, NULL},
-#endif
-#ifndef OPENSSL_NO_TLS1_1
- {TLS1_1_VERSION, tlsv1_1_client_method, tlsv1_1_server_method},
-#else
- {TLS1_1_VERSION, NULL, NULL},
-#endif
-#ifndef OPENSSL_NO_TLS1
- {TLS1_VERSION, tlsv1_client_method, tlsv1_server_method},
-#else
- {TLS1_VERSION, NULL, NULL},
-#endif
-#ifndef OPENSSL_NO_SSL3
- {SSL3_VERSION, sslv3_client_method, sslv3_server_method},
-#else
- {SSL3_VERSION, NULL, NULL},
-#endif
- {0, NULL, NULL},
-};
-
-#if DTLS_MAX_VERSION != DTLS1_2_VERSION
-# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
-#endif
-
-/* Must be in order high to low */
-static const version_info dtls_version_table[] = {
-#ifndef OPENSSL_NO_DTLS1_2
- {DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method},
-#else
- {DTLS1_2_VERSION, NULL, NULL},
-#endif
-#ifndef OPENSSL_NO_DTLS1
- {DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method},
- {DTLS1_BAD_VER, dtls_bad_ver_client_method, NULL},
-#else
- {DTLS1_VERSION, NULL, NULL},
- {DTLS1_BAD_VER, NULL, NULL},
-#endif
- {0, NULL, NULL},
-};
-
-/*
- * ssl_method_error - Check whether an SSL_METHOD is enabled.
- *
- * @s: The SSL handle for the candidate method
- * @method: the intended method.
- *
- * Returns 0 on success, or an SSL error reason on failure.
- */
-static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
-{
- int version = method->version;
-
- if ((s->min_proto_version != 0 &&
- version_cmp(s, version, s->min_proto_version) < 0) ||
- ssl_security(s, SSL_SECOP_VERSION, 0, version, NULL) == 0)
- return SSL_R_VERSION_TOO_LOW;
-
- if (s->max_proto_version != 0 &&
- version_cmp(s, version, s->max_proto_version) > 0)
- return SSL_R_VERSION_TOO_HIGH;
-
- if ((s->options & method->mask) != 0)
- return SSL_R_UNSUPPORTED_PROTOCOL;
- if ((method->flags & SSL_METHOD_NO_SUITEB) != 0 && tls1_suiteb(s))
- return SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE;
-
- return 0;
-}
-
-/*
- * Only called by servers. Returns 1 if the server has a TLSv1.3 capable
+ {X509_V_ERR_CA_MD_TOO_WEAK, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_CERT_CHAIN_TOO_LONG, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_CERT_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED},
+ {X509_V_ERR_CERT_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_CERT_REJECTED, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_CERT_REVOKED, SSL_AD_CERTIFICATE_REVOKED},
+ {X509_V_ERR_CERT_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR},
+ {X509_V_ERR_CERT_UNTRUSTED, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_CRL_HAS_EXPIRED, SSL_AD_CERTIFICATE_EXPIRED},
+ {X509_V_ERR_CRL_NOT_YET_VALID, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_CRL_SIGNATURE_FAILURE, SSL_AD_DECRYPT_ERROR},
+ {X509_V_ERR_DANE_NO_MATCH, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_EE_KEY_TOO_SMALL, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_EMAIL_MISMATCH, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_HOSTNAME_MISMATCH, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_INVALID_CA, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_INVALID_CALL, SSL_AD_INTERNAL_ERROR},
+ {X509_V_ERR_INVALID_PURPOSE, SSL_AD_UNSUPPORTED_CERTIFICATE},
+ {X509_V_ERR_IP_ADDRESS_MISMATCH, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_OUT_OF_MEM, SSL_AD_INTERNAL_ERROR},
+ {X509_V_ERR_PATH_LENGTH_EXCEEDED, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_STORE_LOOKUP, SSL_AD_INTERNAL_ERROR},
+ {X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, SSL_AD_BAD_CERTIFICATE},
+ {X509_V_ERR_UNABLE_TO_GET_CRL, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, SSL_AD_UNKNOWN_CA},
+ {X509_V_ERR_UNSPECIFIED, SSL_AD_INTERNAL_ERROR},
+
+ /* Last entry; return this if we don't find the value above. */
+ {X509_V_OK, SSL_AD_CERTIFICATE_UNKNOWN}
+};
+
+int ssl_x509err2alert(int x509err)
+{
+ const X509ERR2ALERT *tp;
+
+ for (tp = x509table; tp->x509err != X509_V_OK; ++tp)
+ if (tp->x509err == x509err)
+ break;
+ return tp->alert;
+}
+
+int ssl_allow_compression(SSL *s)
+{
+ if (s->options & SSL_OP_NO_COMPRESSION)
+ return 0;
+ return ssl_security(s, SSL_SECOP_COMPRESSION, 0, 0, NULL);
+}
+
+static int version_cmp(const SSL *s, int a, int b)
+{
+ int dtls = SSL_IS_DTLS(s);
+
+ if (a == b)
+ return 0;
+ if (!dtls)
+ return a < b ? -1 : 1;
+ return DTLS_VERSION_LT(a, b) ? -1 : 1;
+}
+
+typedef struct {
+ int version;
+ const SSL_METHOD *(*cmeth) (void);
+ const SSL_METHOD *(*smeth) (void);
+} version_info;
+
+#if TLS_MAX_VERSION != TLS1_3_VERSION
+# error Code needs update for TLS_method() support beyond TLS1_3_VERSION.
+#endif
+
+/* Must be in order high to low */
+static const version_info tls_version_table[] = {
+#ifndef OPENSSL_NO_TLS1_3
+ {TLS1_3_VERSION, tlsv1_3_client_method, tlsv1_3_server_method},
+#else
+ {TLS1_3_VERSION, NULL, NULL},
+#endif
+#ifndef OPENSSL_NO_TLS1_2
+ {TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method},
+#else
+ {TLS1_2_VERSION, NULL, NULL},
+#endif
+#ifndef OPENSSL_NO_TLS1_1
+ {TLS1_1_VERSION, tlsv1_1_client_method, tlsv1_1_server_method},
+#else
+ {TLS1_1_VERSION, NULL, NULL},
+#endif
+#ifndef OPENSSL_NO_TLS1
+ {TLS1_VERSION, tlsv1_client_method, tlsv1_server_method},
+#else
+ {TLS1_VERSION, NULL, NULL},
+#endif
+#ifndef OPENSSL_NO_SSL3
+ {SSL3_VERSION, sslv3_client_method, sslv3_server_method},
+#else
+ {SSL3_VERSION, NULL, NULL},
+#endif
+ {0, NULL, NULL},
+};
+
+#if DTLS_MAX_VERSION != DTLS1_2_VERSION
+# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
+#endif
+
+/* Must be in order high to low */
+static const version_info dtls_version_table[] = {
+#ifndef OPENSSL_NO_DTLS1_2
+ {DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method},
+#else
+ {DTLS1_2_VERSION, NULL, NULL},
+#endif
+#ifndef OPENSSL_NO_DTLS1
+ {DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method},
+ {DTLS1_BAD_VER, dtls_bad_ver_client_method, NULL},
+#else
+ {DTLS1_VERSION, NULL, NULL},
+ {DTLS1_BAD_VER, NULL, NULL},
+#endif
+ {0, NULL, NULL},
+};
+
+/*
+ * ssl_method_error - Check whether an SSL_METHOD is enabled.
+ *
+ * @s: The SSL handle for the candidate method
+ * @method: the intended method.
+ *
+ * Returns 0 on success, or an SSL error reason on failure.
+ */
+static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
+{
+ int version = method->version;
+
+ if ((s->min_proto_version != 0 &&
+ version_cmp(s, version, s->min_proto_version) < 0) ||
+ ssl_security(s, SSL_SECOP_VERSION, 0, version, NULL) == 0)
+ return SSL_R_VERSION_TOO_LOW;
+
+ if (s->max_proto_version != 0 &&
+ version_cmp(s, version, s->max_proto_version) > 0)
+ return SSL_R_VERSION_TOO_HIGH;
+
+ if ((s->options & method->mask) != 0)
+ return SSL_R_UNSUPPORTED_PROTOCOL;
+ if ((method->flags & SSL_METHOD_NO_SUITEB) != 0 && tls1_suiteb(s))
+ return SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE;
+
+ return 0;
+}
+
+/*
+ * Only called by servers. Returns 1 if the server has a TLSv1.3 capable
* certificate type, or has PSK or a certificate callback configured, or has
* a servername callback configured. Otherwise returns 0.
- */
-static int is_tls13_capable(const SSL *s)
-{
- int i;
-#ifndef OPENSSL_NO_EC
- int curve;
- EC_KEY *eckey;
-#endif
-
+ */
+static int is_tls13_capable(const SSL *s)
+{
+ int i;
+#ifndef OPENSSL_NO_EC
+ int curve;
+ EC_KEY *eckey;
+#endif
+
if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL))
return 0;
@@ -1526,156 +1526,156 @@ static int is_tls13_capable(const SSL *s)
|| s->session_ctx->ext.servername_cb != NULL)
return 1;
-#ifndef OPENSSL_NO_PSK
- if (s->psk_server_callback != NULL)
- return 1;
-#endif
-
- if (s->psk_find_session_cb != NULL || s->cert->cert_cb != NULL)
- return 1;
-
- for (i = 0; i < SSL_PKEY_NUM; i++) {
- /* Skip over certs disallowed for TLSv1.3 */
- switch (i) {
- case SSL_PKEY_DSA_SIGN:
- case SSL_PKEY_GOST01:
- case SSL_PKEY_GOST12_256:
- case SSL_PKEY_GOST12_512:
- continue;
- default:
- break;
- }
- if (!ssl_has_cert(s, i))
- continue;
-#ifndef OPENSSL_NO_EC
- if (i != SSL_PKEY_ECC)
- return 1;
- /*
- * Prior to TLSv1.3 sig algs allowed any curve to be used. TLSv1.3 is
- * more restrictive so check that our sig algs are consistent with this
- * EC cert. See section 4.2.3 of RFC8446.
- */
- eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
- if (eckey == NULL)
- continue;
- curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
- if (tls_check_sigalg_curve(s, curve))
- return 1;
-#else
- return 1;
-#endif
- }
-
- return 0;
-}
-
-/*
- * ssl_version_supported - Check that the specified `version` is supported by
- * `SSL *` instance
- *
- * @s: The SSL handle for the candidate method
- * @version: Protocol version to test against
- *
- * Returns 1 when supported, otherwise 0
- */
-int ssl_version_supported(const SSL *s, int version, const SSL_METHOD **meth)
-{
- const version_info *vent;
- const version_info *table;
-
- switch (s->method->version) {
- default:
- /* Version should match method version for non-ANY method */
- return version_cmp(s, version, s->version) == 0;
- case TLS_ANY_VERSION:
- table = tls_version_table;
- break;
- case DTLS_ANY_VERSION:
- table = dtls_version_table;
- break;
- }
-
- for (vent = table;
- vent->version != 0 && version_cmp(s, version, vent->version) <= 0;
- ++vent) {
- if (vent->cmeth != NULL
- && version_cmp(s, version, vent->version) == 0
- && ssl_method_error(s, vent->cmeth()) == 0
- && (!s->server
- || version != TLS1_3_VERSION
- || is_tls13_capable(s))) {
- if (meth != NULL)
- *meth = vent->cmeth();
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * ssl_check_version_downgrade - In response to RFC7507 SCSV version
- * fallback indication from a client check whether we're using the highest
- * supported protocol version.
- *
- * @s server SSL handle.
- *
- * Returns 1 when using the highest enabled version, 0 otherwise.
- */
-int ssl_check_version_downgrade(SSL *s)
-{
- const version_info *vent;
- const version_info *table;
-
- /*
- * Check that the current protocol is the highest enabled version
- * (according to s->ctx->method, as version negotiation may have changed
- * s->method).
- */
- if (s->version == s->ctx->method->version)
- return 1;
-
- /*
- * Apparently we're using a version-flexible SSL_METHOD (not at its
- * highest protocol version).
- */
- if (s->ctx->method->version == TLS_method()->version)
- table = tls_version_table;
- else if (s->ctx->method->version == DTLS_method()->version)
- table = dtls_version_table;
- else {
- /* Unexpected state; fail closed. */
- return 0;
- }
-
- for (vent = table; vent->version != 0; ++vent) {
- if (vent->smeth != NULL && ssl_method_error(s, vent->smeth()) == 0)
- return s->version == vent->version;
- }
- return 0;
-}
-
-/*
- * ssl_set_version_bound - set an upper or lower bound on the supported (D)TLS
- * protocols, provided the initial (D)TLS method is version-flexible. This
- * function sanity-checks the proposed value and makes sure the method is
- * version-flexible, then sets the limit if all is well.
- *
- * @method_version: The version of the current SSL_METHOD.
- * @version: the intended limit.
- * @bound: pointer to limit to be updated.
- *
- * Returns 1 on success, 0 on failure.
- */
-int ssl_set_version_bound(int method_version, int version, int *bound)
-{
+#ifndef OPENSSL_NO_PSK
+ if (s->psk_server_callback != NULL)
+ return 1;
+#endif
+
+ if (s->psk_find_session_cb != NULL || s->cert->cert_cb != NULL)
+ return 1;
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ /* Skip over certs disallowed for TLSv1.3 */
+ switch (i) {
+ case SSL_PKEY_DSA_SIGN:
+ case SSL_PKEY_GOST01:
+ case SSL_PKEY_GOST12_256:
+ case SSL_PKEY_GOST12_512:
+ continue;
+ default:
+ break;
+ }
+ if (!ssl_has_cert(s, i))
+ continue;
+#ifndef OPENSSL_NO_EC
+ if (i != SSL_PKEY_ECC)
+ return 1;
+ /*
+ * Prior to TLSv1.3 sig algs allowed any curve to be used. TLSv1.3 is
+ * more restrictive so check that our sig algs are consistent with this
+ * EC cert. See section 4.2.3 of RFC8446.
+ */
+ eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
+ if (eckey == NULL)
+ continue;
+ curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+ if (tls_check_sigalg_curve(s, curve))
+ return 1;
+#else
+ return 1;
+#endif
+ }
+
+ return 0;
+}
+
+/*
+ * ssl_version_supported - Check that the specified `version` is supported by
+ * `SSL *` instance
+ *
+ * @s: The SSL handle for the candidate method
+ * @version: Protocol version to test against
+ *
+ * Returns 1 when supported, otherwise 0
+ */
+int ssl_version_supported(const SSL *s, int version, const SSL_METHOD **meth)
+{
+ const version_info *vent;
+ const version_info *table;
+
+ switch (s->method->version) {
+ default:
+ /* Version should match method version for non-ANY method */
+ return version_cmp(s, version, s->version) == 0;
+ case TLS_ANY_VERSION:
+ table = tls_version_table;
+ break;
+ case DTLS_ANY_VERSION:
+ table = dtls_version_table;
+ break;
+ }
+
+ for (vent = table;
+ vent->version != 0 && version_cmp(s, version, vent->version) <= 0;
+ ++vent) {
+ if (vent->cmeth != NULL
+ && version_cmp(s, version, vent->version) == 0
+ && ssl_method_error(s, vent->cmeth()) == 0
+ && (!s->server
+ || version != TLS1_3_VERSION
+ || is_tls13_capable(s))) {
+ if (meth != NULL)
+ *meth = vent->cmeth();
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ssl_check_version_downgrade - In response to RFC7507 SCSV version
+ * fallback indication from a client check whether we're using the highest
+ * supported protocol version.
+ *
+ * @s server SSL handle.
+ *
+ * Returns 1 when using the highest enabled version, 0 otherwise.
+ */
+int ssl_check_version_downgrade(SSL *s)
+{
+ const version_info *vent;
+ const version_info *table;
+
+ /*
+ * Check that the current protocol is the highest enabled version
+ * (according to s->ctx->method, as version negotiation may have changed
+ * s->method).
+ */
+ if (s->version == s->ctx->method->version)
+ return 1;
+
+ /*
+ * Apparently we're using a version-flexible SSL_METHOD (not at its
+ * highest protocol version).
+ */
+ if (s->ctx->method->version == TLS_method()->version)
+ table = tls_version_table;
+ else if (s->ctx->method->version == DTLS_method()->version)
+ table = dtls_version_table;
+ else {
+ /* Unexpected state; fail closed. */
+ return 0;
+ }
+
+ for (vent = table; vent->version != 0; ++vent) {
+ if (vent->smeth != NULL && ssl_method_error(s, vent->smeth()) == 0)
+ return s->version == vent->version;
+ }
+ return 0;
+}
+
+/*
+ * ssl_set_version_bound - set an upper or lower bound on the supported (D)TLS
+ * protocols, provided the initial (D)TLS method is version-flexible. This
+ * function sanity-checks the proposed value and makes sure the method is
+ * version-flexible, then sets the limit if all is well.
+ *
+ * @method_version: The version of the current SSL_METHOD.
+ * @version: the intended limit.
+ * @bound: pointer to limit to be updated.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+int ssl_set_version_bound(int method_version, int version, int *bound)
+{
int valid_tls;
int valid_dtls;
- if (version == 0) {
- *bound = version;
- return 1;
- }
-
+ if (version == 0) {
+ *bound = version;
+ return 1;
+ }
+
valid_tls = version >= SSL3_VERSION && version <= TLS_MAX_VERSION;
valid_dtls =
DTLS_VERSION_LE(version, DTLS_MAX_VERSION) &&
@@ -1684,756 +1684,756 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
if (!valid_tls && !valid_dtls)
return 0;
- /*-
- * Restrict TLS methods to TLS protocol versions.
- * Restrict DTLS methods to DTLS protocol versions.
- * Note, DTLS version numbers are decreasing, use comparison macros.
- *
- * Note that for both lower-bounds we use explicit versions, not
- * (D)TLS_MIN_VERSION. This is because we don't want to break user
- * configurations. If the MIN (supported) version ever rises, the user's
- * "floor" remains valid even if no longer available. We don't expect the
- * MAX ceiling to ever get lower, so making that variable makes sense.
+ /*-
+ * Restrict TLS methods to TLS protocol versions.
+ * Restrict DTLS methods to DTLS protocol versions.
+ * Note, DTLS version numbers are decreasing, use comparison macros.
+ *
+ * Note that for both lower-bounds we use explicit versions, not
+ * (D)TLS_MIN_VERSION. This is because we don't want to break user
+ * configurations. If the MIN (supported) version ever rises, the user's
+ * "floor" remains valid even if no longer available. We don't expect the
+ * MAX ceiling to ever get lower, so making that variable makes sense.
*
* We ignore attempts to set bounds on version-inflexible methods,
* returning success.
- */
- switch (method_version) {
- default:
+ */
+ switch (method_version) {
+ default:
break;
-
- case TLS_ANY_VERSION:
+
+ case TLS_ANY_VERSION:
if (valid_tls)
*bound = version;
- break;
-
- case DTLS_ANY_VERSION:
+ break;
+
+ case DTLS_ANY_VERSION:
if (valid_dtls)
*bound = version;
- break;
- }
- return 1;
-}
-
-static void check_for_downgrade(SSL *s, int vers, DOWNGRADE *dgrd)
-{
- if (vers == TLS1_2_VERSION
- && ssl_version_supported(s, TLS1_3_VERSION, NULL)) {
- *dgrd = DOWNGRADE_TO_1_2;
- } else if (!SSL_IS_DTLS(s)
- && vers < TLS1_2_VERSION
- /*
- * We need to ensure that a server that disables TLSv1.2
- * (creating a hole between TLSv1.3 and TLSv1.1) can still
- * complete handshakes with clients that support TLSv1.2 and
- * below. Therefore we do not enable the sentinel if TLSv1.3 is
- * enabled and TLSv1.2 is not.
- */
- && ssl_version_supported(s, TLS1_2_VERSION, NULL)) {
- *dgrd = DOWNGRADE_TO_1_1;
- } else {
- *dgrd = DOWNGRADE_NONE;
- }
-}
-
-/*
- * ssl_choose_server_version - Choose server (D)TLS version. Called when the
- * client HELLO is received to select the final server protocol version and
- * the version specific method.
- *
- * @s: server SSL handle.
- *
- * Returns 0 on success or an SSL error reason number on failure.
- */
-int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
-{
- /*-
- * With version-flexible methods we have an initial state with:
- *
- * s->method->version == (D)TLS_ANY_VERSION,
- * s->version == (D)TLS_MAX_VERSION.
- *
- * So we detect version-flexible methods via the method version, not the
- * handle version.
- */
- int server_version = s->method->version;
- int client_version = hello->legacy_version;
- const version_info *vent;
- const version_info *table;
- int disabled = 0;
- RAW_EXTENSION *suppversions;
-
- s->client_version = client_version;
-
- switch (server_version) {
- default:
- if (!SSL_IS_TLS13(s)) {
- if (version_cmp(s, client_version, s->version) < 0)
- return SSL_R_WRONG_SSL_VERSION;
- *dgrd = DOWNGRADE_NONE;
- /*
- * If this SSL handle is not from a version flexible method we don't
- * (and never did) check min/max FIPS or Suite B constraints. Hope
- * that's OK. It is up to the caller to not choose fixed protocol
- * versions they don't want. If not, then easy to fix, just return
- * ssl_method_error(s, s->method)
- */
- return 0;
- }
- /*
- * Fall through if we are TLSv1.3 already (this means we must be after
- * a HelloRetryRequest
- */
- /* fall thru */
- case TLS_ANY_VERSION:
- table = tls_version_table;
- break;
- case DTLS_ANY_VERSION:
- table = dtls_version_table;
- break;
- }
-
- suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions];
-
- /* If we did an HRR then supported versions is mandatory */
- if (!suppversions->present && s->hello_retry_request != SSL_HRR_NONE)
- return SSL_R_UNSUPPORTED_PROTOCOL;
-
- if (suppversions->present && !SSL_IS_DTLS(s)) {
- unsigned int candidate_vers = 0;
- unsigned int best_vers = 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;
- }
-
- /*
- * The TLSv1.3 spec says the client MUST set this to TLS1_2_VERSION.
- * The spec only requires servers to check that it isn't SSLv3:
- * "Any endpoint receiving a Hello message with
- * ClientHello.legacy_version or ServerHello.legacy_version set to
- * 0x0300 MUST abort the handshake with a "protocol_version" alert."
- * We are slightly stricter and require that it isn't SSLv3 or lower.
- * We tolerate TLSv1 and TLSv1.1.
- */
- if (client_version <= SSL3_VERSION)
- return SSL_R_BAD_LEGACY_VERSION;
-
- while (PACKET_get_net_2(&versionslist, &candidate_vers)) {
- if (version_cmp(s, candidate_vers, best_vers) <= 0)
- continue;
- if (ssl_version_supported(s, candidate_vers, &best_method))
- best_vers = candidate_vers;
- }
- if (PACKET_remaining(&versionslist) != 0) {
- /* Trailing data? */
- return SSL_R_LENGTH_MISMATCH;
- }
-
- if (best_vers > 0) {
- if (s->hello_retry_request != SSL_HRR_NONE) {
- /*
- * This is after a HelloRetryRequest so we better check that we
- * negotiated TLSv1.3
- */
- if (best_vers != TLS1_3_VERSION)
- return SSL_R_UNSUPPORTED_PROTOCOL;
- return 0;
- }
- check_for_downgrade(s, best_vers, dgrd);
- s->version = best_vers;
- s->method = best_method;
- return 0;
- }
- return SSL_R_UNSUPPORTED_PROTOCOL;
- }
-
- /*
- * If the supported versions extension isn't present, then the highest
- * version we can negotiate is TLSv1.2
- */
- if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0)
- client_version = TLS1_2_VERSION;
-
- /*
- * No supported versions extension, so we just use the version supplied in
- * the ClientHello.
- */
- for (vent = table; vent->version != 0; ++vent) {
- const SSL_METHOD *method;
-
- if (vent->smeth == NULL ||
- version_cmp(s, client_version, vent->version) < 0)
- continue;
- method = vent->smeth();
- if (ssl_method_error(s, method) == 0) {
- check_for_downgrade(s, vent->version, dgrd);
- s->version = vent->version;
- s->method = method;
- return 0;
- }
- disabled = 1;
- }
- return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW;
-}
-
-/*
- * ssl_choose_client_version - Choose client (D)TLS version. Called when the
- * server HELLO is received to select the final client protocol version and
- * the version specific method.
- *
- * @s: client SSL handle.
- * @version: The proposed version from the server's HELLO.
- * @extensions: The extensions received
- *
- * Returns 1 on success or 0 on error.
- */
-int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
-{
- const version_info *vent;
- const version_info *table;
- int ret, ver_min, ver_max, real_max, origv;
-
- origv = s->version;
- s->version = version;
-
- /* This will overwrite s->version if the extension is present */
- if (!tls_parse_extension(s, TLSEXT_IDX_supported_versions,
- SSL_EXT_TLS1_2_SERVER_HELLO
- | SSL_EXT_TLS1_3_SERVER_HELLO, extensions,
- NULL, 0)) {
- s->version = origv;
- return 0;
- }
-
- if (s->hello_retry_request != SSL_HRR_NONE
- && s->version != TLS1_3_VERSION) {
- s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_WRONG_SSL_VERSION);
- return 0;
- }
-
- switch (s->method->version) {
- default:
- if (s->version != s->method->version) {
- s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_WRONG_SSL_VERSION);
- return 0;
- }
- /*
- * If this SSL handle is not from a version flexible method we don't
- * (and never did) check min/max, FIPS or Suite B constraints. Hope
- * that's OK. It is up to the caller to not choose fixed protocol
- * versions they don't want. If not, then easy to fix, just return
- * ssl_method_error(s, s->method)
- */
- return 1;
- case TLS_ANY_VERSION:
- table = tls_version_table;
- break;
- case DTLS_ANY_VERSION:
- table = dtls_version_table;
- break;
- }
-
- ret = ssl_get_min_max_version(s, &ver_min, &ver_max, &real_max);
- if (ret != 0) {
- s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION, ret);
- return 0;
- }
- if (SSL_IS_DTLS(s) ? DTLS_VERSION_LT(s->version, ver_min)
- : s->version < ver_min) {
- s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
- return 0;
- } else if (SSL_IS_DTLS(s) ? DTLS_VERSION_GT(s->version, ver_max)
- : s->version > ver_max) {
- s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
- return 0;
- }
-
- if ((s->mode & SSL_MODE_SEND_FALLBACK_SCSV) == 0)
- real_max = ver_max;
-
- /* Check for downgrades */
- if (s->version == TLS1_2_VERSION && real_max > s->version) {
- if (memcmp(tls12downgrade,
- s->s3->server_random + SSL3_RANDOM_SIZE
- - sizeof(tls12downgrade),
- sizeof(tls12downgrade)) == 0) {
- s->version = origv;
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_INAPPROPRIATE_FALLBACK);
- return 0;
- }
- } else if (!SSL_IS_DTLS(s)
- && s->version < TLS1_2_VERSION
- && real_max > s->version) {
- if (memcmp(tls11downgrade,
- s->s3->server_random + SSL3_RANDOM_SIZE
- - sizeof(tls11downgrade),
- sizeof(tls11downgrade)) == 0) {
- s->version = origv;
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_INAPPROPRIATE_FALLBACK);
- return 0;
- }
- }
-
- for (vent = table; vent->version != 0; ++vent) {
- if (vent->cmeth == NULL || s->version != vent->version)
- continue;
-
- s->method = vent->cmeth();
- return 1;
- }
-
- s->version = origv;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
- SSL_R_UNSUPPORTED_PROTOCOL);
- return 0;
-}
-
-/*
- * ssl_get_min_max_version - get minimum and maximum protocol version
- * @s: The SSL connection
- * @min_version: The minimum supported version
- * @max_version: The maximum supported version
- * @real_max: The highest version below the lowest compile time version hole
- * where that hole lies above at least one run-time enabled
- * protocol.
- *
- * Work out what version we should be using for the initial ClientHello if the
- * version is initially (D)TLS_ANY_VERSION. We apply any explicit SSL_OP_NO_xxx
- * options, the MinProtocol and MaxProtocol configuration commands, any Suite B
- * constraints and any floor imposed by the security level here,
- * so we don't advertise the wrong protocol version to only reject the outcome later.
- *
- * Computing the right floor matters. If, e.g., TLS 1.0 and 1.2 are enabled,
- * TLS 1.1 is disabled, but the security level, Suite-B and/or MinProtocol
- * only allow TLS 1.2, we want to advertise TLS1.2, *not* TLS1.
- *
- * Returns 0 on success or an SSL error reason number on failure. On failure
- * min_version and max_version will also be set to 0.
- */
-int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version,
- int *real_max)
-{
- int version, tmp_real_max;
- int hole;
- const SSL_METHOD *single = NULL;
- const SSL_METHOD *method;
- const version_info *table;
- const version_info *vent;
-
- switch (s->method->version) {
- default:
- /*
- * If this SSL handle is not from a version flexible method we don't
- * (and never did) check min/max FIPS or Suite B constraints. Hope
- * that's OK. It is up to the caller to not choose fixed protocol
- * versions they don't want. If not, then easy to fix, just return
- * ssl_method_error(s, s->method)
- */
- *min_version = *max_version = s->version;
- /*
- * Providing a real_max only makes sense where we're using a version
- * flexible method.
- */
- if (!ossl_assert(real_max == NULL))
- return ERR_R_INTERNAL_ERROR;
- return 0;
- case TLS_ANY_VERSION:
- table = tls_version_table;
- break;
- case DTLS_ANY_VERSION:
- table = dtls_version_table;
- break;
- }
-
- /*
- * SSL_OP_NO_X disables all protocols above X *if* there are some protocols
- * below X enabled. This is required in order to maintain the "version
- * capability" vector contiguous. Any versions with a NULL client method
- * (protocol version client is disabled at compile-time) is also a "hole".
- *
- * Our initial state is hole == 1, version == 0. That is, versions above
- * the first version in the method table are disabled (a "hole" above
- * the valid protocol entries) and we don't have a selected version yet.
- *
- * Whenever "hole == 1", and we hit an enabled method, its version becomes
- * the selected version, and the method becomes a candidate "single"
- * method. We're no longer in a hole, so "hole" becomes 0.
- *
- * If "hole == 0" and we hit an enabled method, then "single" is cleared,
- * as we support a contiguous range of at least two methods. If we hit
- * a disabled method, then hole becomes true again, but nothing else
- * changes yet, because all the remaining methods may be disabled too.
- * If we again hit an enabled method after the new hole, it becomes
- * selected, as we start from scratch.
- */
- *min_version = version = 0;
- hole = 1;
- if (real_max != NULL)
- *real_max = 0;
- tmp_real_max = 0;
- for (vent = table; vent->version != 0; ++vent) {
- /*
- * A table entry with a NULL client method is still a hole in the
- * "version capability" vector.
- */
- if (vent->cmeth == NULL) {
- hole = 1;
- tmp_real_max = 0;
- continue;
- }
- method = vent->cmeth();
-
- if (hole == 1 && tmp_real_max == 0)
- tmp_real_max = vent->version;
-
- if (ssl_method_error(s, method) != 0) {
- hole = 1;
- } else if (!hole) {
- single = NULL;
- *min_version = method->version;
- } else {
- if (real_max != NULL && tmp_real_max != 0)
- *real_max = tmp_real_max;
- version = (single = method)->version;
- *min_version = version;
- hole = 0;
- }
- }
-
- *max_version = version;
-
- /* Fail if everything is disabled */
- if (version == 0)
- return SSL_R_NO_PROTOCOLS_AVAILABLE;
-
- return 0;
-}
-
-/*
- * ssl_set_client_hello_version - Work out what version we should be using for
- * the initial ClientHello.legacy_version field.
- *
- * @s: client SSL handle.
- *
- * Returns 0 on success or an SSL error reason number on failure.
- */
-int ssl_set_client_hello_version(SSL *s)
-{
- int ver_min, ver_max, ret;
-
- /*
- * In a renegotiation we always send the same client_version that we sent
- * last time, regardless of which version we eventually negotiated.
- */
- if (!SSL_IS_FIRST_HANDSHAKE(s))
- return 0;
-
- ret = ssl_get_min_max_version(s, &ver_min, &ver_max, NULL);
-
- if (ret != 0)
- return ret;
-
- s->version = ver_max;
-
- /* TLS1.3 always uses TLS1.2 in the legacy_version field */
- if (!SSL_IS_DTLS(s) && ver_max > TLS1_2_VERSION)
- ver_max = TLS1_2_VERSION;
-
- s->client_version = ver_max;
- return 0;
-}
-
-/*
- * 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.
- */
-#ifndef OPENSSL_NO_EC
-int check_in_list(SSL *s, uint16_t group_id, const uint16_t *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++) {
- uint16_t group = groups[i];
-
- if (group_id == group
- && (!checkallow
- || tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) {
- return 1;
- }
- }
-
- return 0;
-}
-#endif
-
-/* Replace ClientHello1 in the transcript hash with a synthetic message */
-int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
- size_t hashlen, const unsigned char *hrr,
- size_t hrrlen)
-{
- unsigned char hashvaltmp[EVP_MAX_MD_SIZE];
- unsigned char msghdr[SSL3_HM_HEADER_LENGTH];
-
- memset(msghdr, 0, sizeof(msghdr));
-
- if (hashval == NULL) {
- hashval = hashvaltmp;
- hashlen = 0;
- /* Get the hash of the initial ClientHello */
- if (!ssl3_digest_cached_records(s, 0)
- || !ssl_handshake_hash(s, hashvaltmp, sizeof(hashvaltmp),
- &hashlen)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
-
- /* Reinitialise the transcript hash */
- if (!ssl3_init_finished_mac(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /* Inject the synthetic message_hash message */
- msghdr[0] = SSL3_MT_MESSAGE_HASH;
- msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen;
- if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH)
- || !ssl3_finish_mac(s, hashval, hashlen)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /*
- * Now re-inject the HRR and current message if appropriate (we just deleted
- * it when we reinitialised the transcript hash above). Only necessary after
- * receiving a ClientHello2 with a cookie.
- */
- if (hrr != NULL
- && (!ssl3_finish_mac(s, hrr, hrrlen)
- || !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->s3->tmp.message_size
- + SSL3_HM_HEADER_LENGTH))) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
-{
- return X509_NAME_cmp(*a, *b);
-}
-
-int parse_ca_names(SSL *s, PACKET *pkt)
-{
- STACK_OF(X509_NAME) *ca_sk = sk_X509_NAME_new(ca_dn_cmp);
- X509_NAME *xn = NULL;
- PACKET cadns;
-
- if (ca_sk == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- /* get the CA RDNs */
- if (!PACKET_get_length_prefixed_2(pkt, &cadns)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- while (PACKET_remaining(&cadns)) {
- const unsigned char *namestart, *namebytes;
- unsigned int name_len;
-
- if (!PACKET_get_net_2(&cadns, &name_len)
- || !PACKET_get_bytes(&cadns, &namebytes, name_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- namestart = namebytes;
- if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
- ERR_R_ASN1_LIB);
- goto err;
- }
- if (namebytes != (namestart + name_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
- SSL_R_CA_DN_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!sk_X509_NAME_push(ca_sk, xn)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- xn = NULL;
- }
-
- sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
- s->s3->tmp.peer_ca_names = ca_sk;
-
- return 1;
-
- err:
- sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
- X509_NAME_free(xn);
- return 0;
-}
-
-const STACK_OF(X509_NAME) *get_ca_names(SSL *s)
-{
- const STACK_OF(X509_NAME) *ca_sk = NULL;;
-
- if (s->server) {
- ca_sk = SSL_get_client_CA_list(s);
- if (ca_sk != NULL && sk_X509_NAME_num(ca_sk) == 0)
- ca_sk = NULL;
- }
-
- if (ca_sk == NULL)
- ca_sk = SSL_get0_CA_list(s);
-
- return ca_sk;
-}
-
-int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt)
-{
- /* Start sub-packet for client CA list */
- if (!WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (ca_sk != NULL) {
- int i;
-
- for (i = 0; i < sk_X509_NAME_num(ca_sk); i++) {
- unsigned char *namebytes;
- X509_NAME *name = sk_X509_NAME_value(ca_sk, i);
- int namelen;
-
- if (name == NULL
- || (namelen = i2d_X509_NAME(name, NULL)) < 0
- || !WPACKET_sub_allocate_bytes_u16(pkt, namelen,
- &namebytes)
- || i2d_X509_NAME(name, &namebytes) != namelen) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- }
-
- if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-/* Create a buffer containing data to be signed for server key exchange */
-size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
- const void *param, size_t paramlen)
-{
- size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen;
- unsigned char *tbs = OPENSSL_malloc(tbslen);
-
- if (tbs == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
- memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE);
- memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE);
-
- memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen);
-
- *ptbs = tbs;
- return tbslen;
-}
-
-/*
- * Saves the current handshake digest for Post-Handshake Auth,
- * Done after ClientFinished is processed, done exactly once
- */
-int tls13_save_handshake_digest_for_pha(SSL *s)
-{
- if (s->pha_dgst == NULL) {
- if (!ssl3_digest_cached_records(s, 1))
- /* SSLfatal() already called */
- return 0;
-
- s->pha_dgst = EVP_MD_CTX_new();
- if (s->pha_dgst == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!EVP_MD_CTX_copy_ex(s->pha_dgst,
- s->s3->handshake_dgst)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * Restores the Post-Handshake Auth handshake digest
- * Done just before sending/processing the Cert Request
- */
-int tls13_restore_handshake_digest_for_pha(SSL *s)
-{
- if (s->pha_dgst == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst,
- s->pha_dgst)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- return 1;
-}
+ break;
+ }
+ return 1;
+}
+
+static void check_for_downgrade(SSL *s, int vers, DOWNGRADE *dgrd)
+{
+ if (vers == TLS1_2_VERSION
+ && ssl_version_supported(s, TLS1_3_VERSION, NULL)) {
+ *dgrd = DOWNGRADE_TO_1_2;
+ } else if (!SSL_IS_DTLS(s)
+ && vers < TLS1_2_VERSION
+ /*
+ * We need to ensure that a server that disables TLSv1.2
+ * (creating a hole between TLSv1.3 and TLSv1.1) can still
+ * complete handshakes with clients that support TLSv1.2 and
+ * below. Therefore we do not enable the sentinel if TLSv1.3 is
+ * enabled and TLSv1.2 is not.
+ */
+ && ssl_version_supported(s, TLS1_2_VERSION, NULL)) {
+ *dgrd = DOWNGRADE_TO_1_1;
+ } else {
+ *dgrd = DOWNGRADE_NONE;
+ }
+}
+
+/*
+ * ssl_choose_server_version - Choose server (D)TLS version. Called when the
+ * client HELLO is received to select the final server protocol version and
+ * the version specific method.
+ *
+ * @s: server SSL handle.
+ *
+ * Returns 0 on success or an SSL error reason number on failure.
+ */
+int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
+{
+ /*-
+ * With version-flexible methods we have an initial state with:
+ *
+ * s->method->version == (D)TLS_ANY_VERSION,
+ * s->version == (D)TLS_MAX_VERSION.
+ *
+ * So we detect version-flexible methods via the method version, not the
+ * handle version.
+ */
+ int server_version = s->method->version;
+ int client_version = hello->legacy_version;
+ const version_info *vent;
+ const version_info *table;
+ int disabled = 0;
+ RAW_EXTENSION *suppversions;
+
+ s->client_version = client_version;
+
+ switch (server_version) {
+ default:
+ if (!SSL_IS_TLS13(s)) {
+ if (version_cmp(s, client_version, s->version) < 0)
+ return SSL_R_WRONG_SSL_VERSION;
+ *dgrd = DOWNGRADE_NONE;
+ /*
+ * If this SSL handle is not from a version flexible method we don't
+ * (and never did) check min/max FIPS or Suite B constraints. Hope
+ * that's OK. It is up to the caller to not choose fixed protocol
+ * versions they don't want. If not, then easy to fix, just return
+ * ssl_method_error(s, s->method)
+ */
+ return 0;
+ }
+ /*
+ * Fall through if we are TLSv1.3 already (this means we must be after
+ * a HelloRetryRequest
+ */
+ /* fall thru */
+ case TLS_ANY_VERSION:
+ table = tls_version_table;
+ break;
+ case DTLS_ANY_VERSION:
+ table = dtls_version_table;
+ break;
+ }
+
+ suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions];
+
+ /* If we did an HRR then supported versions is mandatory */
+ if (!suppversions->present && s->hello_retry_request != SSL_HRR_NONE)
+ return SSL_R_UNSUPPORTED_PROTOCOL;
+
+ if (suppversions->present && !SSL_IS_DTLS(s)) {
+ unsigned int candidate_vers = 0;
+ unsigned int best_vers = 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;
+ }
+
+ /*
+ * The TLSv1.3 spec says the client MUST set this to TLS1_2_VERSION.
+ * The spec only requires servers to check that it isn't SSLv3:
+ * "Any endpoint receiving a Hello message with
+ * ClientHello.legacy_version or ServerHello.legacy_version set to
+ * 0x0300 MUST abort the handshake with a "protocol_version" alert."
+ * We are slightly stricter and require that it isn't SSLv3 or lower.
+ * We tolerate TLSv1 and TLSv1.1.
+ */
+ if (client_version <= SSL3_VERSION)
+ return SSL_R_BAD_LEGACY_VERSION;
+
+ while (PACKET_get_net_2(&versionslist, &candidate_vers)) {
+ if (version_cmp(s, candidate_vers, best_vers) <= 0)
+ continue;
+ if (ssl_version_supported(s, candidate_vers, &best_method))
+ best_vers = candidate_vers;
+ }
+ if (PACKET_remaining(&versionslist) != 0) {
+ /* Trailing data? */
+ return SSL_R_LENGTH_MISMATCH;
+ }
+
+ if (best_vers > 0) {
+ if (s->hello_retry_request != SSL_HRR_NONE) {
+ /*
+ * This is after a HelloRetryRequest so we better check that we
+ * negotiated TLSv1.3
+ */
+ if (best_vers != TLS1_3_VERSION)
+ return SSL_R_UNSUPPORTED_PROTOCOL;
+ return 0;
+ }
+ check_for_downgrade(s, best_vers, dgrd);
+ s->version = best_vers;
+ s->method = best_method;
+ return 0;
+ }
+ return SSL_R_UNSUPPORTED_PROTOCOL;
+ }
+
+ /*
+ * If the supported versions extension isn't present, then the highest
+ * version we can negotiate is TLSv1.2
+ */
+ if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0)
+ client_version = TLS1_2_VERSION;
+
+ /*
+ * No supported versions extension, so we just use the version supplied in
+ * the ClientHello.
+ */
+ for (vent = table; vent->version != 0; ++vent) {
+ const SSL_METHOD *method;
+
+ if (vent->smeth == NULL ||
+ version_cmp(s, client_version, vent->version) < 0)
+ continue;
+ method = vent->smeth();
+ if (ssl_method_error(s, method) == 0) {
+ check_for_downgrade(s, vent->version, dgrd);
+ s->version = vent->version;
+ s->method = method;
+ return 0;
+ }
+ disabled = 1;
+ }
+ return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW;
+}
+
+/*
+ * ssl_choose_client_version - Choose client (D)TLS version. Called when the
+ * server HELLO is received to select the final client protocol version and
+ * the version specific method.
+ *
+ * @s: client SSL handle.
+ * @version: The proposed version from the server's HELLO.
+ * @extensions: The extensions received
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
+{
+ const version_info *vent;
+ const version_info *table;
+ int ret, ver_min, ver_max, real_max, origv;
+
+ origv = s->version;
+ s->version = version;
+
+ /* This will overwrite s->version if the extension is present */
+ if (!tls_parse_extension(s, TLSEXT_IDX_supported_versions,
+ SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_SERVER_HELLO, extensions,
+ NULL, 0)) {
+ s->version = origv;
+ return 0;
+ }
+
+ if (s->hello_retry_request != SSL_HRR_NONE
+ && s->version != TLS1_3_VERSION) {
+ s->version = origv;
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+ SSL_R_WRONG_SSL_VERSION);
+ return 0;
+ }
+
+ switch (s->method->version) {
+ default:
+ if (s->version != s->method->version) {
+ s->version = origv;
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+ SSL_R_WRONG_SSL_VERSION);
+ return 0;
+ }
+ /*
+ * If this SSL handle is not from a version flexible method we don't
+ * (and never did) check min/max, FIPS or Suite B constraints. Hope
+ * that's OK. It is up to the caller to not choose fixed protocol
+ * versions they don't want. If not, then easy to fix, just return
+ * ssl_method_error(s, s->method)
+ */
+ return 1;
+ case TLS_ANY_VERSION:
+ table = tls_version_table;
+ break;
+ case DTLS_ANY_VERSION:
+ table = dtls_version_table;
+ break;
+ }
+
+ ret = ssl_get_min_max_version(s, &ver_min, &ver_max, &real_max);
+ if (ret != 0) {
+ s->version = origv;
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_SSL_CHOOSE_CLIENT_VERSION, ret);
+ return 0;
+ }
+ if (SSL_IS_DTLS(s) ? DTLS_VERSION_LT(s->version, ver_min)
+ : s->version < ver_min) {
+ s->version = origv;
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
+ return 0;
+ } else if (SSL_IS_DTLS(s) ? DTLS_VERSION_GT(s->version, ver_max)
+ : s->version > ver_max) {
+ s->version = origv;
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL);
+ return 0;
+ }
+
+ if ((s->mode & SSL_MODE_SEND_FALLBACK_SCSV) == 0)
+ real_max = ver_max;
+
+ /* Check for downgrades */
+ if (s->version == TLS1_2_VERSION && real_max > s->version) {
+ if (memcmp(tls12downgrade,
+ s->s3->server_random + SSL3_RANDOM_SIZE
+ - sizeof(tls12downgrade),
+ sizeof(tls12downgrade)) == 0) {
+ s->version = origv;
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+ SSL_R_INAPPROPRIATE_FALLBACK);
+ return 0;
+ }
+ } else if (!SSL_IS_DTLS(s)
+ && s->version < TLS1_2_VERSION
+ && real_max > s->version) {
+ if (memcmp(tls11downgrade,
+ s->s3->server_random + SSL3_RANDOM_SIZE
+ - sizeof(tls11downgrade),
+ sizeof(tls11downgrade)) == 0) {
+ s->version = origv;
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+ SSL_R_INAPPROPRIATE_FALLBACK);
+ return 0;
+ }
+ }
+
+ for (vent = table; vent->version != 0; ++vent) {
+ if (vent->cmeth == NULL || s->version != vent->version)
+ continue;
+
+ s->method = vent->cmeth();
+ return 1;
+ }
+
+ s->version = origv;
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+ SSL_R_UNSUPPORTED_PROTOCOL);
+ return 0;
+}
+
+/*
+ * ssl_get_min_max_version - get minimum and maximum protocol version
+ * @s: The SSL connection
+ * @min_version: The minimum supported version
+ * @max_version: The maximum supported version
+ * @real_max: The highest version below the lowest compile time version hole
+ * where that hole lies above at least one run-time enabled
+ * protocol.
+ *
+ * Work out what version we should be using for the initial ClientHello if the
+ * version is initially (D)TLS_ANY_VERSION. We apply any explicit SSL_OP_NO_xxx
+ * options, the MinProtocol and MaxProtocol configuration commands, any Suite B
+ * constraints and any floor imposed by the security level here,
+ * so we don't advertise the wrong protocol version to only reject the outcome later.
+ *
+ * Computing the right floor matters. If, e.g., TLS 1.0 and 1.2 are enabled,
+ * TLS 1.1 is disabled, but the security level, Suite-B and/or MinProtocol
+ * only allow TLS 1.2, we want to advertise TLS1.2, *not* TLS1.
+ *
+ * Returns 0 on success or an SSL error reason number on failure. On failure
+ * min_version and max_version will also be set to 0.
+ */
+int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version,
+ int *real_max)
+{
+ int version, tmp_real_max;
+ int hole;
+ const SSL_METHOD *single = NULL;
+ const SSL_METHOD *method;
+ const version_info *table;
+ const version_info *vent;
+
+ switch (s->method->version) {
+ default:
+ /*
+ * If this SSL handle is not from a version flexible method we don't
+ * (and never did) check min/max FIPS or Suite B constraints. Hope
+ * that's OK. It is up to the caller to not choose fixed protocol
+ * versions they don't want. If not, then easy to fix, just return
+ * ssl_method_error(s, s->method)
+ */
+ *min_version = *max_version = s->version;
+ /*
+ * Providing a real_max only makes sense where we're using a version
+ * flexible method.
+ */
+ if (!ossl_assert(real_max == NULL))
+ return ERR_R_INTERNAL_ERROR;
+ return 0;
+ case TLS_ANY_VERSION:
+ table = tls_version_table;
+ break;
+ case DTLS_ANY_VERSION:
+ table = dtls_version_table;
+ break;
+ }
+
+ /*
+ * SSL_OP_NO_X disables all protocols above X *if* there are some protocols
+ * below X enabled. This is required in order to maintain the "version
+ * capability" vector contiguous. Any versions with a NULL client method
+ * (protocol version client is disabled at compile-time) is also a "hole".
+ *
+ * Our initial state is hole == 1, version == 0. That is, versions above
+ * the first version in the method table are disabled (a "hole" above
+ * the valid protocol entries) and we don't have a selected version yet.
+ *
+ * Whenever "hole == 1", and we hit an enabled method, its version becomes
+ * the selected version, and the method becomes a candidate "single"
+ * method. We're no longer in a hole, so "hole" becomes 0.
+ *
+ * If "hole == 0" and we hit an enabled method, then "single" is cleared,
+ * as we support a contiguous range of at least two methods. If we hit
+ * a disabled method, then hole becomes true again, but nothing else
+ * changes yet, because all the remaining methods may be disabled too.
+ * If we again hit an enabled method after the new hole, it becomes
+ * selected, as we start from scratch.
+ */
+ *min_version = version = 0;
+ hole = 1;
+ if (real_max != NULL)
+ *real_max = 0;
+ tmp_real_max = 0;
+ for (vent = table; vent->version != 0; ++vent) {
+ /*
+ * A table entry with a NULL client method is still a hole in the
+ * "version capability" vector.
+ */
+ if (vent->cmeth == NULL) {
+ hole = 1;
+ tmp_real_max = 0;
+ continue;
+ }
+ method = vent->cmeth();
+
+ if (hole == 1 && tmp_real_max == 0)
+ tmp_real_max = vent->version;
+
+ if (ssl_method_error(s, method) != 0) {
+ hole = 1;
+ } else if (!hole) {
+ single = NULL;
+ *min_version = method->version;
+ } else {
+ if (real_max != NULL && tmp_real_max != 0)
+ *real_max = tmp_real_max;
+ version = (single = method)->version;
+ *min_version = version;
+ hole = 0;
+ }
+ }
+
+ *max_version = version;
+
+ /* Fail if everything is disabled */
+ if (version == 0)
+ return SSL_R_NO_PROTOCOLS_AVAILABLE;
+
+ return 0;
+}
+
+/*
+ * ssl_set_client_hello_version - Work out what version we should be using for
+ * the initial ClientHello.legacy_version field.
+ *
+ * @s: client SSL handle.
+ *
+ * Returns 0 on success or an SSL error reason number on failure.
+ */
+int ssl_set_client_hello_version(SSL *s)
+{
+ int ver_min, ver_max, ret;
+
+ /*
+ * In a renegotiation we always send the same client_version that we sent
+ * last time, regardless of which version we eventually negotiated.
+ */
+ if (!SSL_IS_FIRST_HANDSHAKE(s))
+ return 0;
+
+ ret = ssl_get_min_max_version(s, &ver_min, &ver_max, NULL);
+
+ if (ret != 0)
+ return ret;
+
+ s->version = ver_max;
+
+ /* TLS1.3 always uses TLS1.2 in the legacy_version field */
+ if (!SSL_IS_DTLS(s) && ver_max > TLS1_2_VERSION)
+ ver_max = TLS1_2_VERSION;
+
+ s->client_version = ver_max;
+ return 0;
+}
+
+/*
+ * 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.
+ */
+#ifndef OPENSSL_NO_EC
+int check_in_list(SSL *s, uint16_t group_id, const uint16_t *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++) {
+ uint16_t group = groups[i];
+
+ if (group_id == group
+ && (!checkallow
+ || tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+/* Replace ClientHello1 in the transcript hash with a synthetic message */
+int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
+ size_t hashlen, const unsigned char *hrr,
+ size_t hrrlen)
+{
+ unsigned char hashvaltmp[EVP_MAX_MD_SIZE];
+ unsigned char msghdr[SSL3_HM_HEADER_LENGTH];
+
+ memset(msghdr, 0, sizeof(msghdr));
+
+ if (hashval == NULL) {
+ hashval = hashvaltmp;
+ hashlen = 0;
+ /* Get the hash of the initial ClientHello */
+ if (!ssl3_digest_cached_records(s, 0)
+ || !ssl_handshake_hash(s, hashvaltmp, sizeof(hashvaltmp),
+ &hashlen)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+
+ /* Reinitialise the transcript hash */
+ if (!ssl3_init_finished_mac(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ /* Inject the synthetic message_hash message */
+ msghdr[0] = SSL3_MT_MESSAGE_HASH;
+ msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen;
+ if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH)
+ || !ssl3_finish_mac(s, hashval, hashlen)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ /*
+ * Now re-inject the HRR and current message if appropriate (we just deleted
+ * it when we reinitialised the transcript hash above). Only necessary after
+ * receiving a ClientHello2 with a cookie.
+ */
+ if (hrr != NULL
+ && (!ssl3_finish_mac(s, hrr, hrrlen)
+ || !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->s3->tmp.message_size
+ + SSL3_HM_HEADER_LENGTH))) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
+{
+ return X509_NAME_cmp(*a, *b);
+}
+
+int parse_ca_names(SSL *s, PACKET *pkt)
+{
+ STACK_OF(X509_NAME) *ca_sk = sk_X509_NAME_new(ca_dn_cmp);
+ X509_NAME *xn = NULL;
+ PACKET cadns;
+
+ if (ca_sk == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* get the CA RDNs */
+ if (!PACKET_get_length_prefixed_2(pkt, &cadns)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ while (PACKET_remaining(&cadns)) {
+ const unsigned char *namestart, *namebytes;
+ unsigned int name_len;
+
+ if (!PACKET_get_net_2(&cadns, &name_len)
+ || !PACKET_get_bytes(&cadns, &namebytes, name_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ namestart = namebytes;
+ if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
+ ERR_R_ASN1_LIB);
+ goto err;
+ }
+ if (namebytes != (namestart + name_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
+ SSL_R_CA_DN_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!sk_X509_NAME_push(ca_sk, xn)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ xn = NULL;
+ }
+
+ sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
+ s->s3->tmp.peer_ca_names = ca_sk;
+
+ return 1;
+
+ err:
+ sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
+ X509_NAME_free(xn);
+ return 0;
+}
+
+const STACK_OF(X509_NAME) *get_ca_names(SSL *s)
+{
+ const STACK_OF(X509_NAME) *ca_sk = NULL;;
+
+ if (s->server) {
+ ca_sk = SSL_get_client_CA_list(s);
+ if (ca_sk != NULL && sk_X509_NAME_num(ca_sk) == 0)
+ ca_sk = NULL;
+ }
+
+ if (ca_sk == NULL)
+ ca_sk = SSL_get0_CA_list(s);
+
+ return ca_sk;
+}
+
+int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt)
+{
+ /* Start sub-packet for client CA list */
+ if (!WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (ca_sk != NULL) {
+ int i;
+
+ for (i = 0; i < sk_X509_NAME_num(ca_sk); i++) {
+ unsigned char *namebytes;
+ X509_NAME *name = sk_X509_NAME_value(ca_sk, i);
+ int namelen;
+
+ if (name == NULL
+ || (namelen = i2d_X509_NAME(name, NULL)) < 0
+ || !WPACKET_sub_allocate_bytes_u16(pkt, namelen,
+ &namebytes)
+ || i2d_X509_NAME(name, &namebytes) != namelen) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ }
+
+ if (!WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Create a buffer containing data to be signed for server key exchange */
+size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
+ const void *param, size_t paramlen)
+{
+ size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen;
+ unsigned char *tbs = OPENSSL_malloc(tbslen);
+
+ if (tbs == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE);
+ memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE);
+
+ memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen);
+
+ *ptbs = tbs;
+ return tbslen;
+}
+
+/*
+ * Saves the current handshake digest for Post-Handshake Auth,
+ * Done after ClientFinished is processed, done exactly once
+ */
+int tls13_save_handshake_digest_for_pha(SSL *s)
+{
+ if (s->pha_dgst == NULL) {
+ if (!ssl3_digest_cached_records(s, 1))
+ /* SSLfatal() already called */
+ return 0;
+
+ s->pha_dgst = EVP_MD_CTX_new();
+ if (s->pha_dgst == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!EVP_MD_CTX_copy_ex(s->pha_dgst,
+ s->s3->handshake_dgst)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Restores the Post-Handshake Auth handshake digest
+ * Done just before sending/processing the Cert Request
+ */
+int tls13_restore_handshake_digest_for_pha(SSL *s)
+{
+ if (s->pha_dgst == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst,
+ s->pha_dgst)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ return 1;
+}
diff --git a/contrib/libs/openssl/ssl/statem/statem_srvr.c b/contrib/libs/openssl/ssl/statem/statem_srvr.c
index d701c46b43..206668ce80 100644
--- a/contrib/libs/openssl/ssl/statem/statem_srvr.c
+++ b/contrib/libs/openssl/ssl/statem/statem_srvr.c
@@ -1,32 +1,32 @@
-/*
+/*
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
- * Copyright 2005 Nokia. 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 <stdio.h>
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ * Copyright 2005 Nokia. 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 <stdio.h>
#include "../ssl_local.h"
#include "statem_local.h"
#include "internal/constant_time.h"
-#include "internal/cryptlib.h"
-#include <openssl/buffer.h>
-#include <openssl/rand.h>
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/x509.h>
-#include <openssl/dh.h>
-#include <openssl/bn.h>
-#include <openssl/md5.h>
+#include "internal/cryptlib.h"
+#include <openssl/buffer.h>
+#include <openssl/rand.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/x509.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/md5.h>
#include <openssl/asn1t.h>
-
-#define TICKET_NONCE_SIZE 8
-
+
+#define TICKET_NONCE_SIZE 8
+
typedef struct {
ASN1_TYPE *kxBlob;
ASN1_TYPE *opaqueBlob;
@@ -41,708 +41,708 @@ ASN1_SEQUENCE(GOST_KX_MESSAGE) = {
IMPLEMENT_ASN1_FUNCTIONS(GOST_KX_MESSAGE)
-static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt);
-
-/*
- * ossl_statem_server13_read_transition() encapsulates the logic for the allowed
- * handshake state transitions when a TLSv1.3 server is reading messages from
- * the client. The message type that the client has sent is provided in |mt|.
- * The current state is in |s->statem.hand_state|.
- *
- * Return values are 1 for success (transition allowed) and 0 on error
- * (transition not allowed)
- */
-static int ossl_statem_server13_read_transition(SSL *s, int mt)
-{
- OSSL_STATEM *st = &s->statem;
-
- /*
- * Note: There is no case for TLS_ST_BEFORE because at that stage we have
- * not negotiated TLSv1.3 yet, so that case is handled by
- * ossl_statem_server_read_transition()
- */
- switch (st->hand_state) {
- default:
- break;
-
- case TLS_ST_EARLY_DATA:
- if (s->hello_retry_request == SSL_HRR_PENDING) {
- if (mt == SSL3_MT_CLIENT_HELLO) {
- st->hand_state = TLS_ST_SR_CLNT_HELLO;
- return 1;
- }
- break;
- } else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
- if (mt == SSL3_MT_END_OF_EARLY_DATA) {
- st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
- return 1;
- }
- break;
- }
- /* Fall through */
-
- case TLS_ST_SR_END_OF_EARLY_DATA:
- case TLS_ST_SW_FINISHED:
- if (s->s3->tmp.cert_request) {
- if (mt == SSL3_MT_CERTIFICATE) {
- st->hand_state = TLS_ST_SR_CERT;
- return 1;
- }
- } else {
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_SR_FINISHED;
- return 1;
- }
- }
- break;
-
- case TLS_ST_SR_CERT:
- if (s->session->peer == NULL) {
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_SR_FINISHED;
- return 1;
- }
- } else {
- if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
- st->hand_state = TLS_ST_SR_CERT_VRFY;
- return 1;
- }
- }
- break;
-
- case TLS_ST_SR_CERT_VRFY:
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_SR_FINISHED;
- return 1;
- }
- break;
-
- case TLS_ST_OK:
- /*
- * Its never ok to start processing handshake messages in the middle of
- * early data (i.e. before we've received the end of early data alert)
- */
- if (s->early_data_state == SSL_EARLY_DATA_READING)
- break;
-
- if (mt == SSL3_MT_CERTIFICATE
- && s->post_handshake_auth == SSL_PHA_REQUESTED) {
- st->hand_state = TLS_ST_SR_CERT;
- return 1;
- }
-
- if (mt == SSL3_MT_KEY_UPDATE) {
- st->hand_state = TLS_ST_SR_KEY_UPDATE;
- return 1;
- }
- break;
- }
-
- /* No valid transition found */
- return 0;
-}
-
-/*
- * ossl_statem_server_read_transition() encapsulates the logic for the allowed
- * handshake state transitions when the server is reading messages from the
- * client. The message type that the client has sent is provided in |mt|. The
- * current state is in |s->statem.hand_state|.
- *
- * Return values are 1 for success (transition allowed) and 0 on error
- * (transition not allowed)
- */
-int ossl_statem_server_read_transition(SSL *s, int mt)
-{
- OSSL_STATEM *st = &s->statem;
-
- if (SSL_IS_TLS13(s)) {
- if (!ossl_statem_server13_read_transition(s, mt))
- goto err;
- return 1;
- }
-
- switch (st->hand_state) {
- default:
- break;
-
- case TLS_ST_BEFORE:
- case TLS_ST_OK:
- case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
- if (mt == SSL3_MT_CLIENT_HELLO) {
- st->hand_state = TLS_ST_SR_CLNT_HELLO;
- return 1;
- }
- break;
-
- case TLS_ST_SW_SRVR_DONE:
- /*
- * If we get a CKE message after a ServerDone then either
- * 1) We didn't request a Certificate
- * OR
- * 2) If we did request one then
- * a) We allow no Certificate to be returned
- * AND
- * b) We are running SSL3 (in TLS1.0+ the client must return a 0
- * list if we requested a certificate)
- */
- if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
- if (s->s3->tmp.cert_request) {
- if (s->version == SSL3_VERSION) {
- if ((s->verify_mode & SSL_VERIFY_PEER)
- && (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
- /*
- * This isn't an unexpected message as such - we're just
- * not going to accept it because we require a client
- * cert.
- */
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
- SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
- return 0;
- }
- st->hand_state = TLS_ST_SR_KEY_EXCH;
- return 1;
- }
- } else {
- st->hand_state = TLS_ST_SR_KEY_EXCH;
- return 1;
- }
- } else if (s->s3->tmp.cert_request) {
- if (mt == SSL3_MT_CERTIFICATE) {
- st->hand_state = TLS_ST_SR_CERT;
- return 1;
- }
- }
- break;
-
- case TLS_ST_SR_CERT:
- if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
- st->hand_state = TLS_ST_SR_KEY_EXCH;
- return 1;
- }
- break;
-
- case TLS_ST_SR_KEY_EXCH:
- /*
- * We should only process a CertificateVerify message if we have
- * received a Certificate from the client. If so then |s->session->peer|
- * will be non NULL. In some instances a CertificateVerify message is
- * not required even if the peer has sent a Certificate (e.g. such as in
- * the case of static DH). In that case |st->no_cert_verify| should be
- * set.
- */
- if (s->session->peer == NULL || st->no_cert_verify) {
- if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- /*
- * For the ECDH ciphersuites when the client sends its ECDH
- * pub key in a certificate, the CertificateVerify message is
- * not sent. Also for GOST ciphersuites when the client uses
- * its key from the certificate for key exchange.
- */
- st->hand_state = TLS_ST_SR_CHANGE;
- return 1;
- }
- } else {
- if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
- st->hand_state = TLS_ST_SR_CERT_VRFY;
- return 1;
- }
- }
- break;
-
- case TLS_ST_SR_CERT_VRFY:
- if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- st->hand_state = TLS_ST_SR_CHANGE;
- return 1;
- }
- break;
-
- case TLS_ST_SR_CHANGE:
-#ifndef OPENSSL_NO_NEXTPROTONEG
- if (s->s3->npn_seen) {
- if (mt == SSL3_MT_NEXT_PROTO) {
- st->hand_state = TLS_ST_SR_NEXT_PROTO;
- return 1;
- }
- } else {
-#endif
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_SR_FINISHED;
- return 1;
- }
-#ifndef OPENSSL_NO_NEXTPROTONEG
- }
-#endif
- break;
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
- case TLS_ST_SR_NEXT_PROTO:
- if (mt == SSL3_MT_FINISHED) {
- st->hand_state = TLS_ST_SR_FINISHED;
- return 1;
- }
- break;
-#endif
-
- case TLS_ST_SW_FINISHED:
- if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- st->hand_state = TLS_ST_SR_CHANGE;
- return 1;
- }
- break;
- }
-
- err:
- /* No valid transition found */
- if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
- BIO *rbio;
-
- /*
- * CCS messages don't have a message sequence number so this is probably
- * because of an out-of-order CCS. We'll just drop it.
- */
- s->init_num = 0;
- s->rwstate = SSL_READING;
- rbio = SSL_get_rbio(s);
- BIO_clear_retry_flags(rbio);
- BIO_set_retry_read(rbio);
- return 0;
- }
- SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
- SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
- SSL_R_UNEXPECTED_MESSAGE);
- return 0;
-}
-
-/*
- * Should we send a ServerKeyExchange message?
- *
- * Valid return values are:
- * 1: Yes
- * 0: No
- */
-static int send_server_key_exchange(SSL *s)
-{
- unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-
- /*
- * only send a ServerKeyExchange if DH or fortezza but we have a
- * sign only certificate PSK: may send PSK identity hints For
- * ECC ciphersuites, we send a serverKeyExchange message only if
- * the cipher suite is either ECDH-anon or ECDHE. In other cases,
- * the server certificate contains the server's public key for
- * key exchange.
- */
- if (alg_k & (SSL_kDHE | SSL_kECDHE)
- /*
- * PSK: send ServerKeyExchange if PSK identity hint if
- * provided
- */
-#ifndef OPENSSL_NO_PSK
- /* Only send SKE if we have identity hint for plain PSK */
- || ((alg_k & (SSL_kPSK | SSL_kRSAPSK))
- && s->cert->psk_identity_hint)
- /* For other PSK always send SKE */
- || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK)))
-#endif
-#ifndef OPENSSL_NO_SRP
- /* SRP: send ServerKeyExchange */
- || (alg_k & SSL_kSRP)
-#endif
- ) {
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Should we send a CertificateRequest message?
- *
- * Valid return values are:
- * 1: Yes
- * 0: No
- */
-int send_certificate_request(SSL *s)
-{
- if (
- /* don't request cert unless asked for it: */
- s->verify_mode & SSL_VERIFY_PEER
- /*
- * don't request if post-handshake-only unless doing
- * post-handshake in TLSv1.3:
- */
- && (!SSL_IS_TLS13(s) || !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE)
- || s->post_handshake_auth == SSL_PHA_REQUEST_PENDING)
- /*
- * if SSL_VERIFY_CLIENT_ONCE is set, don't request cert
- * a second time:
- */
- && (s->certreqs_sent < 1 ||
- !(s->verify_mode & SSL_VERIFY_CLIENT_ONCE))
- /*
- * never request cert in anonymous ciphersuites (see
- * section "Certificate request" in SSL 3 drafts and in
- * RFC 2246):
- */
- && (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
- /*
- * ... except when the application insists on
- * verification (against the specs, but statem_clnt.c accepts
- * this for SSL 3)
- */
- || (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
- /* don't request certificate for SRP auth */
- && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
- /*
- * With normal PSK Certificates and Certificate Requests
- * are omitted
- */
- && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)) {
- return 1;
- }
-
- return 0;
-}
-
-/*
- * ossl_statem_server13_write_transition() works out what handshake state to
- * move to next when a TLSv1.3 server is writing messages to be sent to the
- * client.
- */
-static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- /*
- * No case for TLS_ST_BEFORE, because at that stage we have not negotiated
- * TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition()
- */
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
- return WRITE_TRAN_ERROR;
-
- case TLS_ST_OK:
- if (s->key_update != SSL_KEY_UPDATE_NONE) {
- st->hand_state = TLS_ST_SW_KEY_UPDATE;
- return WRITE_TRAN_CONTINUE;
- }
- if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
- st->hand_state = TLS_ST_SW_CERT_REQ;
- return WRITE_TRAN_CONTINUE;
- }
- /* Try to read from the client instead */
- return WRITE_TRAN_FINISHED;
-
- case TLS_ST_SR_CLNT_HELLO:
- st->hand_state = TLS_ST_SW_SRVR_HELLO;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_SRVR_HELLO:
- if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
- && s->hello_retry_request != SSL_HRR_COMPLETE)
- st->hand_state = TLS_ST_SW_CHANGE;
- else if (s->hello_retry_request == SSL_HRR_PENDING)
- st->hand_state = TLS_ST_EARLY_DATA;
- else
- st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_CHANGE:
- if (s->hello_retry_request == SSL_HRR_PENDING)
- st->hand_state = TLS_ST_EARLY_DATA;
- else
- st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
- if (s->hit)
- st->hand_state = TLS_ST_SW_FINISHED;
- else if (send_certificate_request(s))
- st->hand_state = TLS_ST_SW_CERT_REQ;
- else
- st->hand_state = TLS_ST_SW_CERT;
-
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_CERT_REQ:
- if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
- s->post_handshake_auth = SSL_PHA_REQUESTED;
- st->hand_state = TLS_ST_OK;
- } else {
- st->hand_state = TLS_ST_SW_CERT;
- }
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_CERT:
- st->hand_state = TLS_ST_SW_CERT_VRFY;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_CERT_VRFY:
- st->hand_state = TLS_ST_SW_FINISHED;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_FINISHED:
- st->hand_state = TLS_ST_EARLY_DATA;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_EARLY_DATA:
- return WRITE_TRAN_FINISHED;
-
- case TLS_ST_SR_FINISHED:
- /*
- * Technically we have finished the handshake at this point, but we're
- * going to remain "in_init" for now and write out any session tickets
- * immediately.
- */
- if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
- s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
- } else if (!s->ext.ticket_expected) {
- /*
- * If we're not going to renew the ticket then we just finish the
- * handshake at this point.
- */
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
- }
- if (s->num_tickets > s->sent_tickets)
- st->hand_state = TLS_ST_SW_SESSION_TICKET;
- else
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SR_KEY_UPDATE:
- case TLS_ST_SW_KEY_UPDATE:
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_SESSION_TICKET:
- /* In a resumption we only ever send a maximum of one new ticket.
- * Following an initial handshake we send the number of tickets we have
- * been configured for.
- */
- if (s->hit || s->num_tickets <= s->sent_tickets) {
- /* We've written enough tickets out. */
- st->hand_state = TLS_ST_OK;
- }
- return WRITE_TRAN_CONTINUE;
- }
-}
-
-/*
- * ossl_statem_server_write_transition() works out what handshake state to move
- * to next when the server is writing messages to be sent to the client.
- */
-WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- /*
- * Note that before the ClientHello we don't know what version we are going
- * to negotiate yet, so we don't take this branch until later
- */
-
- if (SSL_IS_TLS13(s))
- return ossl_statem_server13_write_transition(s);
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION,
- ERR_R_INTERNAL_ERROR);
- return WRITE_TRAN_ERROR;
-
- case TLS_ST_OK:
- if (st->request_state == TLS_ST_SW_HELLO_REQ) {
- /* We must be trying to renegotiate */
- st->hand_state = TLS_ST_SW_HELLO_REQ;
- st->request_state = TLS_ST_BEFORE;
- return WRITE_TRAN_CONTINUE;
- }
- /* Must be an incoming ClientHello */
- if (!tls_setup_handshake(s)) {
- /* SSLfatal() already called */
- return WRITE_TRAN_ERROR;
- }
- /* Fall through */
-
- case TLS_ST_BEFORE:
- /* Just go straight to trying to read from the client */
- return WRITE_TRAN_FINISHED;
-
- case TLS_ST_SW_HELLO_REQ:
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SR_CLNT_HELLO:
- if (SSL_IS_DTLS(s) && !s->d1->cookie_verified
- && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) {
- st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST;
- } else if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
- /* We must have rejected the renegotiation */
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
- } else {
- st->hand_state = TLS_ST_SW_SRVR_HELLO;
- }
- return WRITE_TRAN_CONTINUE;
-
- case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
- return WRITE_TRAN_FINISHED;
-
- case TLS_ST_SW_SRVR_HELLO:
- if (s->hit) {
- if (s->ext.ticket_expected)
- st->hand_state = TLS_ST_SW_SESSION_TICKET;
- else
- st->hand_state = TLS_ST_SW_CHANGE;
- } else {
- /* Check if it is anon DH or anon ECDH, */
- /* normal PSK or SRP */
- if (!(s->s3->tmp.new_cipher->algorithm_auth &
- (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
- st->hand_state = TLS_ST_SW_CERT;
- } else if (send_server_key_exchange(s)) {
- st->hand_state = TLS_ST_SW_KEY_EXCH;
- } else if (send_certificate_request(s)) {
- st->hand_state = TLS_ST_SW_CERT_REQ;
- } else {
- st->hand_state = TLS_ST_SW_SRVR_DONE;
- }
- }
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_CERT:
- if (s->ext.status_expected) {
- st->hand_state = TLS_ST_SW_CERT_STATUS;
- return WRITE_TRAN_CONTINUE;
- }
- /* Fall through */
-
- case TLS_ST_SW_CERT_STATUS:
- if (send_server_key_exchange(s)) {
- st->hand_state = TLS_ST_SW_KEY_EXCH;
- return WRITE_TRAN_CONTINUE;
- }
- /* Fall through */
-
- case TLS_ST_SW_KEY_EXCH:
- if (send_certificate_request(s)) {
- st->hand_state = TLS_ST_SW_CERT_REQ;
- return WRITE_TRAN_CONTINUE;
- }
- /* Fall through */
-
- case TLS_ST_SW_CERT_REQ:
- st->hand_state = TLS_ST_SW_SRVR_DONE;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_SRVR_DONE:
- return WRITE_TRAN_FINISHED;
-
- case TLS_ST_SR_FINISHED:
- if (s->hit) {
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
- } else if (s->ext.ticket_expected) {
- st->hand_state = TLS_ST_SW_SESSION_TICKET;
- } else {
- st->hand_state = TLS_ST_SW_CHANGE;
- }
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_SESSION_TICKET:
- st->hand_state = TLS_ST_SW_CHANGE;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_CHANGE:
- st->hand_state = TLS_ST_SW_FINISHED;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_FINISHED:
- if (s->hit) {
- return WRITE_TRAN_FINISHED;
- }
- st->hand_state = TLS_ST_OK;
- return WRITE_TRAN_CONTINUE;
- }
-}
-
-/*
- * Perform any pre work that needs to be done prior to sending a message from
- * the server to the client.
- */
-WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* No pre work to be done */
- break;
-
- case TLS_ST_SW_HELLO_REQ:
- s->shutdown = 0;
- if (SSL_IS_DTLS(s))
- dtls1_clear_sent_buffer(s);
- break;
-
- case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
- s->shutdown = 0;
- if (SSL_IS_DTLS(s)) {
- dtls1_clear_sent_buffer(s);
- /* We don't buffer this message so don't use the timer */
- st->use_timer = 0;
- }
- break;
-
- case TLS_ST_SW_SRVR_HELLO:
- if (SSL_IS_DTLS(s)) {
- /*
- * Messages we write from now on should be buffered and
- * retransmitted if necessary, so we need to use the timer now
- */
- st->use_timer = 1;
- }
- break;
-
- case TLS_ST_SW_SRVR_DONE:
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
- /* Calls SSLfatal() as required */
- return dtls_wait_for_dry(s);
- }
-#endif
- return WORK_FINISHED_CONTINUE;
-
- case TLS_ST_SW_SESSION_TICKET:
- if (SSL_IS_TLS13(s) && s->sent_tickets == 0) {
- /*
- * Actually this is the end of the handshake, but we're going
- * straight into writing the session ticket out. So we finish off
- * the handshake, but keep the various buffers active.
- *
- * Calls SSLfatal as required.
- */
- return tls_finish_handshake(s, wst, 0, 0);
- } if (SSL_IS_DTLS(s)) {
- /*
- * We're into the last flight. We don't retransmit the last flight
- * unless we need to, so we don't use the timer
- */
- st->use_timer = 0;
- }
- break;
-
- case TLS_ST_SW_CHANGE:
- if (SSL_IS_TLS13(s))
- break;
+static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt);
+
+/*
+ * ossl_statem_server13_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when a TLSv1.3 server is reading messages from
+ * the client. The message type that the client has sent is provided in |mt|.
+ * The current state is in |s->statem.hand_state|.
+ *
+ * Return values are 1 for success (transition allowed) and 0 on error
+ * (transition not allowed)
+ */
+static int ossl_statem_server13_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note: There is no case for TLS_ST_BEFORE because at that stage we have
+ * not negotiated TLSv1.3 yet, so that case is handled by
+ * ossl_statem_server_read_transition()
+ */
+ switch (st->hand_state) {
+ default:
+ break;
+
+ case TLS_ST_EARLY_DATA:
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
+ if (mt == SSL3_MT_CLIENT_HELLO) {
+ st->hand_state = TLS_ST_SR_CLNT_HELLO;
+ return 1;
+ }
+ break;
+ } else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
+ if (mt == SSL3_MT_END_OF_EARLY_DATA) {
+ st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
+ return 1;
+ }
+ break;
+ }
+ /* Fall through */
+
+ case TLS_ST_SR_END_OF_EARLY_DATA:
+ case TLS_ST_SW_FINISHED:
+ if (s->s3->tmp.cert_request) {
+ if (mt == SSL3_MT_CERTIFICATE) {
+ st->hand_state = TLS_ST_SR_CERT;
+ return 1;
+ }
+ } else {
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_SR_FINISHED;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_SR_CERT:
+ if (s->session->peer == NULL) {
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_SR_FINISHED;
+ return 1;
+ }
+ } else {
+ if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
+ st->hand_state = TLS_ST_SR_CERT_VRFY;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_SR_CERT_VRFY:
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_SR_FINISHED;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_OK:
+ /*
+ * Its never ok to start processing handshake messages in the middle of
+ * early data (i.e. before we've received the end of early data alert)
+ */
+ if (s->early_data_state == SSL_EARLY_DATA_READING)
+ break;
+
+ if (mt == SSL3_MT_CERTIFICATE
+ && s->post_handshake_auth == SSL_PHA_REQUESTED) {
+ st->hand_state = TLS_ST_SR_CERT;
+ return 1;
+ }
+
+ if (mt == SSL3_MT_KEY_UPDATE) {
+ st->hand_state = TLS_ST_SR_KEY_UPDATE;
+ return 1;
+ }
+ break;
+ }
+
+ /* No valid transition found */
+ return 0;
+}
+
+/*
+ * ossl_statem_server_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when the server is reading messages from the
+ * client. The message type that the client has sent is provided in |mt|. The
+ * current state is in |s->statem.hand_state|.
+ *
+ * Return values are 1 for success (transition allowed) and 0 on error
+ * (transition not allowed)
+ */
+int ossl_statem_server_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ if (SSL_IS_TLS13(s)) {
+ if (!ossl_statem_server13_read_transition(s, mt))
+ goto err;
+ return 1;
+ }
+
+ switch (st->hand_state) {
+ default:
+ break;
+
+ case TLS_ST_BEFORE:
+ case TLS_ST_OK:
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ if (mt == SSL3_MT_CLIENT_HELLO) {
+ st->hand_state = TLS_ST_SR_CLNT_HELLO;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_SW_SRVR_DONE:
+ /*
+ * If we get a CKE message after a ServerDone then either
+ * 1) We didn't request a Certificate
+ * OR
+ * 2) If we did request one then
+ * a) We allow no Certificate to be returned
+ * AND
+ * b) We are running SSL3 (in TLS1.0+ the client must return a 0
+ * list if we requested a certificate)
+ */
+ if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
+ if (s->s3->tmp.cert_request) {
+ if (s->version == SSL3_VERSION) {
+ if ((s->verify_mode & SSL_VERIFY_PEER)
+ && (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
+ /*
+ * This isn't an unexpected message as such - we're just
+ * not going to accept it because we require a client
+ * cert.
+ */
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
+ SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+ return 0;
+ }
+ st->hand_state = TLS_ST_SR_KEY_EXCH;
+ return 1;
+ }
+ } else {
+ st->hand_state = TLS_ST_SR_KEY_EXCH;
+ return 1;
+ }
+ } else if (s->s3->tmp.cert_request) {
+ if (mt == SSL3_MT_CERTIFICATE) {
+ st->hand_state = TLS_ST_SR_CERT;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_SR_CERT:
+ if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
+ st->hand_state = TLS_ST_SR_KEY_EXCH;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_SR_KEY_EXCH:
+ /*
+ * We should only process a CertificateVerify message if we have
+ * received a Certificate from the client. If so then |s->session->peer|
+ * will be non NULL. In some instances a CertificateVerify message is
+ * not required even if the peer has sent a Certificate (e.g. such as in
+ * the case of static DH). In that case |st->no_cert_verify| should be
+ * set.
+ */
+ if (s->session->peer == NULL || st->no_cert_verify) {
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ /*
+ * For the ECDH ciphersuites when the client sends its ECDH
+ * pub key in a certificate, the CertificateVerify message is
+ * not sent. Also for GOST ciphersuites when the client uses
+ * its key from the certificate for key exchange.
+ */
+ st->hand_state = TLS_ST_SR_CHANGE;
+ return 1;
+ }
+ } else {
+ if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
+ st->hand_state = TLS_ST_SR_CERT_VRFY;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_SR_CERT_VRFY:
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_SR_CHANGE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_SR_CHANGE:
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ if (s->s3->npn_seen) {
+ if (mt == SSL3_MT_NEXT_PROTO) {
+ st->hand_state = TLS_ST_SR_NEXT_PROTO;
+ return 1;
+ }
+ } else {
+#endif
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_SR_FINISHED;
+ return 1;
+ }
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ }
+#endif
+ break;
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ case TLS_ST_SR_NEXT_PROTO:
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_SR_FINISHED;
+ return 1;
+ }
+ break;
+#endif
+
+ case TLS_ST_SW_FINISHED:
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_SR_CHANGE;
+ return 1;
+ }
+ break;
+ }
+
+ err:
+ /* No valid transition found */
+ if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ BIO *rbio;
+
+ /*
+ * CCS messages don't have a message sequence number so this is probably
+ * because of an out-of-order CCS. We'll just drop it.
+ */
+ s->init_num = 0;
+ s->rwstate = SSL_READING;
+ rbio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(rbio);
+ BIO_set_retry_read(rbio);
+ return 0;
+ }
+ SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
+ SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
+ SSL_R_UNEXPECTED_MESSAGE);
+ return 0;
+}
+
+/*
+ * Should we send a ServerKeyExchange message?
+ *
+ * Valid return values are:
+ * 1: Yes
+ * 0: No
+ */
+static int send_server_key_exchange(SSL *s)
+{
+ unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ /*
+ * only send a ServerKeyExchange if DH or fortezza but we have a
+ * sign only certificate PSK: may send PSK identity hints For
+ * ECC ciphersuites, we send a serverKeyExchange message only if
+ * the cipher suite is either ECDH-anon or ECDHE. In other cases,
+ * the server certificate contains the server's public key for
+ * key exchange.
+ */
+ if (alg_k & (SSL_kDHE | SSL_kECDHE)
+ /*
+ * PSK: send ServerKeyExchange if PSK identity hint if
+ * provided
+ */
+#ifndef OPENSSL_NO_PSK
+ /* Only send SKE if we have identity hint for plain PSK */
+ || ((alg_k & (SSL_kPSK | SSL_kRSAPSK))
+ && s->cert->psk_identity_hint)
+ /* For other PSK always send SKE */
+ || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK)))
+#endif
+#ifndef OPENSSL_NO_SRP
+ /* SRP: send ServerKeyExchange */
+ || (alg_k & SSL_kSRP)
+#endif
+ ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Should we send a CertificateRequest message?
+ *
+ * Valid return values are:
+ * 1: Yes
+ * 0: No
+ */
+int send_certificate_request(SSL *s)
+{
+ if (
+ /* don't request cert unless asked for it: */
+ s->verify_mode & SSL_VERIFY_PEER
+ /*
+ * don't request if post-handshake-only unless doing
+ * post-handshake in TLSv1.3:
+ */
+ && (!SSL_IS_TLS13(s) || !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE)
+ || s->post_handshake_auth == SSL_PHA_REQUEST_PENDING)
+ /*
+ * if SSL_VERIFY_CLIENT_ONCE is set, don't request cert
+ * a second time:
+ */
+ && (s->certreqs_sent < 1 ||
+ !(s->verify_mode & SSL_VERIFY_CLIENT_ONCE))
+ /*
+ * never request cert in anonymous ciphersuites (see
+ * section "Certificate request" in SSL 3 drafts and in
+ * RFC 2246):
+ */
+ && (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
+ /*
+ * ... except when the application insists on
+ * verification (against the specs, but statem_clnt.c accepts
+ * this for SSL 3)
+ */
+ || (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
+ /* don't request certificate for SRP auth */
+ && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
+ /*
+ * With normal PSK Certificates and Certificate Requests
+ * are omitted
+ */
+ && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * ossl_statem_server13_write_transition() works out what handshake state to
+ * move to next when a TLSv1.3 server is writing messages to be sent to the
+ * client.
+ */
+static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * No case for TLS_ST_BEFORE, because at that stage we have not negotiated
+ * TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition()
+ */
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION,
+ ERR_R_INTERNAL_ERROR);
+ return WRITE_TRAN_ERROR;
+
+ case TLS_ST_OK:
+ if (s->key_update != SSL_KEY_UPDATE_NONE) {
+ st->hand_state = TLS_ST_SW_KEY_UPDATE;
+ return WRITE_TRAN_CONTINUE;
+ }
+ if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
+ st->hand_state = TLS_ST_SW_CERT_REQ;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Try to read from the client instead */
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_SR_CLNT_HELLO:
+ st->hand_state = TLS_ST_SW_SRVR_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
+ && s->hello_retry_request != SSL_HRR_COMPLETE)
+ st->hand_state = TLS_ST_SW_CHANGE;
+ else if (s->hello_retry_request == SSL_HRR_PENDING)
+ st->hand_state = TLS_ST_EARLY_DATA;
+ else
+ st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CHANGE:
+ if (s->hello_retry_request == SSL_HRR_PENDING)
+ st->hand_state = TLS_ST_EARLY_DATA;
+ else
+ st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
+ if (s->hit)
+ st->hand_state = TLS_ST_SW_FINISHED;
+ else if (send_certificate_request(s))
+ st->hand_state = TLS_ST_SW_CERT_REQ;
+ else
+ st->hand_state = TLS_ST_SW_CERT;
+
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CERT_REQ:
+ if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
+ s->post_handshake_auth = SSL_PHA_REQUESTED;
+ st->hand_state = TLS_ST_OK;
+ } else {
+ st->hand_state = TLS_ST_SW_CERT;
+ }
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CERT:
+ st->hand_state = TLS_ST_SW_CERT_VRFY;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CERT_VRFY:
+ st->hand_state = TLS_ST_SW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_FINISHED:
+ st->hand_state = TLS_ST_EARLY_DATA;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_EARLY_DATA:
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_SR_FINISHED:
+ /*
+ * Technically we have finished the handshake at this point, but we're
+ * going to remain "in_init" for now and write out any session tickets
+ * immediately.
+ */
+ if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
+ s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
+ } else if (!s->ext.ticket_expected) {
+ /*
+ * If we're not going to renew the ticket then we just finish the
+ * handshake at this point.
+ */
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+ }
+ if (s->num_tickets > s->sent_tickets)
+ st->hand_state = TLS_ST_SW_SESSION_TICKET;
+ else
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SR_KEY_UPDATE:
+ case TLS_ST_SW_KEY_UPDATE:
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_SESSION_TICKET:
+ /* In a resumption we only ever send a maximum of one new ticket.
+ * Following an initial handshake we send the number of tickets we have
+ * been configured for.
+ */
+ if (s->hit || s->num_tickets <= s->sent_tickets) {
+ /* We've written enough tickets out. */
+ st->hand_state = TLS_ST_OK;
+ }
+ return WRITE_TRAN_CONTINUE;
+ }
+}
+
+/*
+ * ossl_statem_server_write_transition() works out what handshake state to move
+ * to next when the server is writing messages to be sent to the client.
+ */
+WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note that before the ClientHello we don't know what version we are going
+ * to negotiate yet, so we don't take this branch until later
+ */
+
+ if (SSL_IS_TLS13(s))
+ return ossl_statem_server13_write_transition(s);
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION,
+ ERR_R_INTERNAL_ERROR);
+ return WRITE_TRAN_ERROR;
+
+ case TLS_ST_OK:
+ if (st->request_state == TLS_ST_SW_HELLO_REQ) {
+ /* We must be trying to renegotiate */
+ st->hand_state = TLS_ST_SW_HELLO_REQ;
+ st->request_state = TLS_ST_BEFORE;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Must be an incoming ClientHello */
+ if (!tls_setup_handshake(s)) {
+ /* SSLfatal() already called */
+ return WRITE_TRAN_ERROR;
+ }
+ /* Fall through */
+
+ case TLS_ST_BEFORE:
+ /* Just go straight to trying to read from the client */
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_SW_HELLO_REQ:
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SR_CLNT_HELLO:
+ if (SSL_IS_DTLS(s) && !s->d1->cookie_verified
+ && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) {
+ st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST;
+ } else if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
+ /* We must have rejected the renegotiation */
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+ } else {
+ st->hand_state = TLS_ST_SW_SRVR_HELLO;
+ }
+ return WRITE_TRAN_CONTINUE;
+
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ if (s->hit) {
+ if (s->ext.ticket_expected)
+ st->hand_state = TLS_ST_SW_SESSION_TICKET;
+ else
+ st->hand_state = TLS_ST_SW_CHANGE;
+ } else {
+ /* Check if it is anon DH or anon ECDH, */
+ /* normal PSK or SRP */
+ if (!(s->s3->tmp.new_cipher->algorithm_auth &
+ (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
+ st->hand_state = TLS_ST_SW_CERT;
+ } else if (send_server_key_exchange(s)) {
+ st->hand_state = TLS_ST_SW_KEY_EXCH;
+ } else if (send_certificate_request(s)) {
+ st->hand_state = TLS_ST_SW_CERT_REQ;
+ } else {
+ st->hand_state = TLS_ST_SW_SRVR_DONE;
+ }
+ }
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CERT:
+ if (s->ext.status_expected) {
+ st->hand_state = TLS_ST_SW_CERT_STATUS;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_SW_CERT_STATUS:
+ if (send_server_key_exchange(s)) {
+ st->hand_state = TLS_ST_SW_KEY_EXCH;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_SW_KEY_EXCH:
+ if (send_certificate_request(s)) {
+ st->hand_state = TLS_ST_SW_CERT_REQ;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_SW_CERT_REQ:
+ st->hand_state = TLS_ST_SW_SRVR_DONE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_SRVR_DONE:
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_SR_FINISHED:
+ if (s->hit) {
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+ } else if (s->ext.ticket_expected) {
+ st->hand_state = TLS_ST_SW_SESSION_TICKET;
+ } else {
+ st->hand_state = TLS_ST_SW_CHANGE;
+ }
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_SESSION_TICKET:
+ st->hand_state = TLS_ST_SW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CHANGE:
+ st->hand_state = TLS_ST_SW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_FINISHED:
+ if (s->hit) {
+ return WRITE_TRAN_FINISHED;
+ }
+ st->hand_state = TLS_ST_OK;
+ return WRITE_TRAN_CONTINUE;
+ }
+}
+
+/*
+ * Perform any pre work that needs to be done prior to sending a message from
+ * the server to the client.
+ */
+WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* No pre work to be done */
+ break;
+
+ case TLS_ST_SW_HELLO_REQ:
+ s->shutdown = 0;
+ if (SSL_IS_DTLS(s))
+ dtls1_clear_sent_buffer(s);
+ break;
+
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ s->shutdown = 0;
+ if (SSL_IS_DTLS(s)) {
+ dtls1_clear_sent_buffer(s);
+ /* We don't buffer this message so don't use the timer */
+ st->use_timer = 0;
+ }
+ break;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * Messages we write from now on should be buffered and
+ * retransmitted if necessary, so we need to use the timer now
+ */
+ st->use_timer = 1;
+ }
+ break;
+
+ case TLS_ST_SW_SRVR_DONE:
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+ /* Calls SSLfatal() as required */
+ return dtls_wait_for_dry(s);
+ }
+#endif
+ return WORK_FINISHED_CONTINUE;
+
+ case TLS_ST_SW_SESSION_TICKET:
+ if (SSL_IS_TLS13(s) && s->sent_tickets == 0) {
+ /*
+ * Actually this is the end of the handshake, but we're going
+ * straight into writing the session ticket out. So we finish off
+ * the handshake, but keep the various buffers active.
+ *
+ * Calls SSLfatal as required.
+ */
+ return tls_finish_handshake(s, wst, 0, 0);
+ } if (SSL_IS_DTLS(s)) {
+ /*
+ * We're into the last flight. We don't retransmit the last flight
+ * unless we need to, so we don't use the timer
+ */
+ st->use_timer = 0;
+ }
+ break;
+
+ case TLS_ST_SW_CHANGE:
+ if (SSL_IS_TLS13(s))
+ break;
/* Writes to s->session are only safe for initial handshakes */
if (s->session->cipher == NULL) {
s->session->cipher = s->s3->tmp.new_cipher;
@@ -752,2115 +752,2115 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
- if (!s->method->ssl3_enc->setup_key_block(s)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- if (SSL_IS_DTLS(s)) {
- /*
- * We're into the last flight. We don't retransmit the last flight
- * unless we need to, so we don't use the timer. This might have
- * already been set to 0 if we sent a NewSessionTicket message,
- * but we'll set it again here in case we didn't.
- */
- st->use_timer = 0;
- }
- return WORK_FINISHED_CONTINUE;
-
- case TLS_ST_EARLY_DATA:
- if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING
- && (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
- return WORK_FINISHED_CONTINUE;
- /* Fall through */
-
- case TLS_ST_OK:
- /* Calls SSLfatal() as required */
- return tls_finish_handshake(s, wst, 1, 1);
- }
-
- return WORK_FINISHED_CONTINUE;
-}
-
-static ossl_inline int conn_is_closed(void)
-{
- switch (get_last_sys_error()) {
-#if defined(EPIPE)
- case EPIPE:
- return 1;
-#endif
-#if defined(ECONNRESET)
- case ECONNRESET:
- return 1;
-#endif
+ if (!s->method->ssl3_enc->setup_key_block(s)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ if (SSL_IS_DTLS(s)) {
+ /*
+ * We're into the last flight. We don't retransmit the last flight
+ * unless we need to, so we don't use the timer. This might have
+ * already been set to 0 if we sent a NewSessionTicket message,
+ * but we'll set it again here in case we didn't.
+ */
+ st->use_timer = 0;
+ }
+ return WORK_FINISHED_CONTINUE;
+
+ case TLS_ST_EARLY_DATA:
+ if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING
+ && (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
+ return WORK_FINISHED_CONTINUE;
+ /* Fall through */
+
+ case TLS_ST_OK:
+ /* Calls SSLfatal() as required */
+ return tls_finish_handshake(s, wst, 1, 1);
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+static ossl_inline int conn_is_closed(void)
+{
+ switch (get_last_sys_error()) {
+#if defined(EPIPE)
+ case EPIPE:
+ return 1;
+#endif
+#if defined(ECONNRESET)
+ case ECONNRESET:
+ return 1;
+#endif
#if defined(WSAECONNRESET)
case WSAECONNRESET:
return 1;
#endif
- default:
- return 0;
- }
-}
-
-/*
- * Perform any work that needs to be done after sending a message from the
- * server to the client.
- */
-WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
-{
- OSSL_STATEM *st = &s->statem;
-
- s->init_num = 0;
-
- switch (st->hand_state) {
- default:
- /* No post work to be done */
- break;
-
- case TLS_ST_SW_HELLO_REQ:
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
- if (!ssl3_init_finished_mac(s)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- break;
-
- case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
- /* HelloVerifyRequest resets Finished MAC */
- if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- /*
- * The next message should be another ClientHello which we need to
- * treat like it was the first packet
- */
- s->first_packet = 1;
- break;
-
- case TLS_ST_SW_SRVR_HELLO:
- if (SSL_IS_TLS13(s) && s->hello_retry_request == SSL_HRR_PENDING) {
- if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
- && statem_flush(s) != 1)
- return WORK_MORE_A;
- break;
- }
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s) && s->hit) {
- unsigned char sctpauthkey[64];
- char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
- size_t labellen;
-
- /*
- * Add new shared key for SCTP-Auth, will be ignored if no
- * SCTP used.
- */
- memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
- sizeof(DTLS1_SCTP_AUTH_LABEL));
-
- /* Don't include the terminating zero. */
- labellen = sizeof(labelbuffer) - 1;
- if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
- labellen += 1;
-
- if (SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- labellen, NULL, 0,
- 0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_POST_WORK,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
- }
-
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
- sizeof(sctpauthkey), sctpauthkey);
- }
-#endif
- if (!SSL_IS_TLS13(s)
- || ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
- && s->hello_retry_request != SSL_HRR_COMPLETE))
- break;
- /* Fall through */
-
- case TLS_ST_SW_CHANGE:
- if (s->hello_retry_request == SSL_HRR_PENDING) {
- if (!statem_flush(s))
- return WORK_MORE_A;
- break;
- }
-
- if (SSL_IS_TLS13(s)) {
- if (!s->method->ssl3_enc->setup_key_block(s)
- || !s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
-
- if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED
- && !s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- /*
- * We don't yet know whether the next record we are going to receive
- * is an unencrypted alert, an encrypted alert, or an encrypted
- * handshake message. We temporarily tolerate unencrypted alerts.
- */
- s->statem.enc_read_state = ENC_READ_STATE_ALLOW_PLAIN_ALERTS;
- break;
- }
-
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s) && !s->hit) {
- /*
- * Change to new shared key of SCTP-Auth, will be ignored if
- * no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
- 0, NULL);
- }
-#endif
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CHANGE_CIPHER_SERVER_WRITE))
- {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
-
- if (SSL_IS_DTLS(s))
- dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
- break;
-
- case TLS_ST_SW_SRVR_DONE:
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
- break;
-
- case TLS_ST_SW_FINISHED:
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
-#ifndef OPENSSL_NO_SCTP
- if (SSL_IS_DTLS(s) && s->hit) {
- /*
- * Change to new shared key of SCTP-Auth, will be ignored if
- * no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
- 0, NULL);
- }
-#endif
- if (SSL_IS_TLS13(s)) {
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Perform any work that needs to be done after sending a message from the
+ * server to the client.
+ */
+WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ s->init_num = 0;
+
+ switch (st->hand_state) {
+ default:
+ /* No post work to be done */
+ break;
+
+ case TLS_ST_SW_HELLO_REQ:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ if (!ssl3_init_finished_mac(s)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ break;
+
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ /* HelloVerifyRequest resets Finished MAC */
+ if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ /*
+ * The next message should be another ClientHello which we need to
+ * treat like it was the first packet
+ */
+ s->first_packet = 1;
+ break;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ if (SSL_IS_TLS13(s) && s->hello_retry_request == SSL_HRR_PENDING) {
+ if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
+ && statem_flush(s) != 1)
+ return WORK_MORE_A;
+ break;
+ }
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && s->hit) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+ size_t labellen;
+
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no
+ * SCTP used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ /* Don't include the terminating zero. */
+ labellen = sizeof(labelbuffer) - 1;
+ if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+ labellen += 1;
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ labellen, NULL, 0,
+ 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_SERVER_POST_WORK,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+ }
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+#endif
+ if (!SSL_IS_TLS13(s)
+ || ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
+ && s->hello_retry_request != SSL_HRR_COMPLETE))
+ break;
+ /* Fall through */
+
+ case TLS_ST_SW_CHANGE:
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
+ if (!statem_flush(s))
+ return WORK_MORE_A;
+ break;
+ }
+
+ if (SSL_IS_TLS13(s)) {
+ if (!s->method->ssl3_enc->setup_key_block(s)
+ || !s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+
+ if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED
+ && !s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ /*
+ * We don't yet know whether the next record we are going to receive
+ * is an unencrypted alert, an encrypted alert, or an encrypted
+ * handshake message. We temporarily tolerate unencrypted alerts.
+ */
+ s->statem.enc_read_state = ENC_READ_STATE_ALLOW_PLAIN_ALERTS;
+ break;
+ }
+
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && !s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CHANGE_CIPHER_SERVER_WRITE))
+ {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+
+ if (SSL_IS_DTLS(s))
+ dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ break;
+
+ case TLS_ST_SW_SRVR_DONE:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ break;
+
+ case TLS_ST_SW_FINISHED:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+#ifndef OPENSSL_NO_SCTP
+ if (SSL_IS_DTLS(s) && s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
+ }
+#endif
+ if (SSL_IS_TLS13(s)) {
/* TLS 1.3 gets the secret size from the handshake md */
size_t dummy;
- if (!s->method->ssl3_enc->generate_master_secret(s,
- s->master_secret, s->handshake_secret, 0,
+ if (!s->method->ssl3_enc->generate_master_secret(s,
+ s->master_secret, s->handshake_secret, 0,
&dummy)
- || !s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE))
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- break;
-
- case TLS_ST_SW_CERT_REQ:
- if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
- }
- break;
-
- case TLS_ST_SW_KEY_UPDATE:
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
- if (!tls13_update_key(s, 1)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- break;
-
- case TLS_ST_SW_SESSION_TICKET:
- clear_sys_error();
- if (SSL_IS_TLS13(s) && statem_flush(s) != 1) {
- if (SSL_get_error(s, 0) == SSL_ERROR_SYSCALL
- && conn_is_closed()) {
- /*
- * We ignore connection closed errors in TLSv1.3 when sending a
- * NewSessionTicket and behave as if we were successful. This is
- * so that we are still able to read data sent to us by a client
- * that closes soon after the end of the handshake without
- * waiting to read our post-handshake NewSessionTickets.
- */
- s->rwstate = SSL_NOTHING;
- break;
- }
-
- return WORK_MORE_A;
- }
- break;
- }
-
- return WORK_FINISHED_CONTINUE;
-}
-
-/*
- * Get the message construction function and message type for sending from the
- * server
- *
- * Valid return values are:
- * 1: Success
- * 0: Error
- */
-int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
- confunc_f *confunc, int *mt)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE,
- SSL_R_BAD_HANDSHAKE_STATE);
- return 0;
-
- case TLS_ST_SW_CHANGE:
- if (SSL_IS_DTLS(s))
- *confunc = dtls_construct_change_cipher_spec;
- else
- *confunc = tls_construct_change_cipher_spec;
- *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
- break;
-
- case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
- *confunc = dtls_construct_hello_verify_request;
- *mt = DTLS1_MT_HELLO_VERIFY_REQUEST;
- break;
-
- case TLS_ST_SW_HELLO_REQ:
- /* No construction function needed */
- *confunc = NULL;
- *mt = SSL3_MT_HELLO_REQUEST;
- break;
-
- case TLS_ST_SW_SRVR_HELLO:
- *confunc = tls_construct_server_hello;
- *mt = SSL3_MT_SERVER_HELLO;
- break;
-
- case TLS_ST_SW_CERT:
- *confunc = tls_construct_server_certificate;
- *mt = SSL3_MT_CERTIFICATE;
- break;
-
- case TLS_ST_SW_CERT_VRFY:
- *confunc = tls_construct_cert_verify;
- *mt = SSL3_MT_CERTIFICATE_VERIFY;
- break;
-
-
- case TLS_ST_SW_KEY_EXCH:
- *confunc = tls_construct_server_key_exchange;
- *mt = SSL3_MT_SERVER_KEY_EXCHANGE;
- break;
-
- case TLS_ST_SW_CERT_REQ:
- *confunc = tls_construct_certificate_request;
- *mt = SSL3_MT_CERTIFICATE_REQUEST;
- break;
-
- case TLS_ST_SW_SRVR_DONE:
- *confunc = tls_construct_server_done;
- *mt = SSL3_MT_SERVER_DONE;
- break;
-
- case TLS_ST_SW_SESSION_TICKET:
- *confunc = tls_construct_new_session_ticket;
- *mt = SSL3_MT_NEWSESSION_TICKET;
- break;
-
- case TLS_ST_SW_CERT_STATUS:
- *confunc = tls_construct_cert_status;
- *mt = SSL3_MT_CERTIFICATE_STATUS;
- break;
-
- case TLS_ST_SW_FINISHED:
- *confunc = tls_construct_finished;
- *mt = SSL3_MT_FINISHED;
- break;
-
- case TLS_ST_EARLY_DATA:
- *confunc = NULL;
- *mt = SSL3_MT_DUMMY;
- break;
-
- case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
- *confunc = tls_construct_encrypted_extensions;
- *mt = SSL3_MT_ENCRYPTED_EXTENSIONS;
- break;
-
- case TLS_ST_SW_KEY_UPDATE:
- *confunc = tls_construct_key_update;
- *mt = SSL3_MT_KEY_UPDATE;
- break;
- }
-
- return 1;
-}
-
-/*
- * Maximum size (excluding the Handshake header) of a ClientHello message,
- * calculated as follows:
- *
- * 2 + # client_version
- * 32 + # only valid length for random
- * 1 + # length of session_id
- * 32 + # maximum size for session_id
- * 2 + # length of cipher suites
- * 2^16-2 + # maximum length of cipher suites array
- * 1 + # length of compression_methods
- * 2^8-1 + # maximum length of compression methods
- * 2 + # length of extensions
- * 2^16-1 # maximum length of extensions
- */
-#define CLIENT_HELLO_MAX_LENGTH 131396
-
-#define CLIENT_KEY_EXCH_MAX_LENGTH 2048
-#define NEXT_PROTO_MAX_LENGTH 514
-
-/*
- * Returns the maximum allowed length for the current message that we are
- * reading. Excludes the message header.
- */
-size_t ossl_statem_server_max_message_size(SSL *s)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- return 0;
-
- case TLS_ST_SR_CLNT_HELLO:
- return CLIENT_HELLO_MAX_LENGTH;
-
- case TLS_ST_SR_END_OF_EARLY_DATA:
- return END_OF_EARLY_DATA_MAX_LENGTH;
-
- case TLS_ST_SR_CERT:
- return s->max_cert_list;
-
- case TLS_ST_SR_KEY_EXCH:
- return CLIENT_KEY_EXCH_MAX_LENGTH;
-
- case TLS_ST_SR_CERT_VRFY:
- return SSL3_RT_MAX_PLAIN_LENGTH;
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
- case TLS_ST_SR_NEXT_PROTO:
- return NEXT_PROTO_MAX_LENGTH;
-#endif
-
- case TLS_ST_SR_CHANGE:
- return CCS_MAX_LENGTH;
-
- case TLS_ST_SR_FINISHED:
- return FINISHED_MAX_LENGTH;
-
- case TLS_ST_SR_KEY_UPDATE:
- return KEY_UPDATE_MAX_LENGTH;
- }
-}
-
-/*
- * Process a message that the server has received from the client.
- */
-MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
- return MSG_PROCESS_ERROR;
-
- case TLS_ST_SR_CLNT_HELLO:
- return tls_process_client_hello(s, pkt);
-
- case TLS_ST_SR_END_OF_EARLY_DATA:
- return tls_process_end_of_early_data(s, pkt);
-
- case TLS_ST_SR_CERT:
- return tls_process_client_certificate(s, pkt);
-
- case TLS_ST_SR_KEY_EXCH:
- return tls_process_client_key_exchange(s, pkt);
-
- case TLS_ST_SR_CERT_VRFY:
- return tls_process_cert_verify(s, pkt);
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
- case TLS_ST_SR_NEXT_PROTO:
- return tls_process_next_proto(s, pkt);
-#endif
-
- case TLS_ST_SR_CHANGE:
- return tls_process_change_cipher_spec(s, pkt);
-
- case TLS_ST_SR_FINISHED:
- return tls_process_finished(s, pkt);
-
- case TLS_ST_SR_KEY_UPDATE:
- return tls_process_key_update(s, pkt);
-
- }
-}
-
-/*
- * Perform any further processing required following the receipt of a message
- * from the client
- */
-WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
-{
- OSSL_STATEM *st = &s->statem;
-
- switch (st->hand_state) {
- default:
- /* Shouldn't happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
-
- case TLS_ST_SR_CLNT_HELLO:
- return tls_post_process_client_hello(s, wst);
-
- case TLS_ST_SR_KEY_EXCH:
- return tls_post_process_client_key_exchange(s, wst);
- }
-}
-
-#ifndef OPENSSL_NO_SRP
-/* Returns 1 on success, 0 for retryable error, -1 for fatal error */
-static int ssl_check_srp_ext_ClientHello(SSL *s)
-{
- int ret;
- int al = SSL_AD_UNRECOGNIZED_NAME;
-
- if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
- (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
- if (s->srp_ctx.login == NULL) {
- /*
- * RFC 5054 says SHOULD reject, we do so if There is no srp
- * login name
- */
- SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
- SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
- SSL_R_PSK_IDENTITY_NOT_FOUND);
- return -1;
- } else {
- ret = SSL_srp_server_param_with_username(s, &al);
- if (ret < 0)
- return 0;
- if (ret == SSL3_AL_FATAL) {
- SSLfatal(s, al, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
- al == SSL_AD_UNKNOWN_PSK_IDENTITY
- ? SSL_R_PSK_IDENTITY_NOT_FOUND
- : SSL_R_CLIENTHELLO_TLSEXT);
- return -1;
- }
- }
- }
- return 1;
-}
-#endif
-
-int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
- size_t cookie_len)
-{
- /* Always use DTLS 1.0 version: see RFC 6347 */
- if (!WPACKET_put_bytes_u16(pkt, DTLS1_VERSION)
- || !WPACKET_sub_memcpy_u8(pkt, cookie, cookie_len))
- return 0;
-
- return 1;
-}
-
-int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
-{
- unsigned int cookie_leni;
- if (s->ctx->app_gen_cookie_cb == NULL ||
- s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
- &cookie_leni) == 0 ||
- cookie_leni > 255) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
- SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
- return 0;
- }
- s->d1->cookie_len = cookie_leni;
-
- if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
- s->d1->cookie_len)) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- 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
- * signature_algorithms (for TLSv1.2 only)
- *
- * 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)
-{
- 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;
- unsigned int type;
- PACKET sni, tmppkt;
- size_t ext_len;
-
- 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 */
-
-MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
-{
- /* |cookie| will only be initialized for DTLS. */
- PACKET session_id, compression, extensions, cookie;
- static const unsigned char null_compression = 0;
- CLIENTHELLO_MSG *clienthello = NULL;
-
- /* Check if this is actually an unexpected renegotiation ClientHello */
- if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
- if (!ossl_assert(!SSL_IS_TLS13(s))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0
- || (!s->s3->send_connection_binding
- && (s->options
- & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) {
- ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
- return MSG_PROCESS_FINISHED_READING;
- }
- s->renegotiate = 1;
- s->new_session = 1;
- }
-
- clienthello = OPENSSL_zalloc(sizeof(*clienthello));
- if (clienthello == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure.
- */
- clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer);
- PACKET_null_init(&cookie);
-
- if (clienthello->isv2) {
- unsigned int mt;
-
- if (!SSL_IS_FIRST_HANDSHAKE(s)
- || s->hello_retry_request != SSL_HRR_NONE) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
- goto err;
- }
-
- /*-
- * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
- * header is sent directly on the wire, not wrapped as a TLS
- * record. Our record layer just processes the message length and passes
- * the rest right through. Its format is:
- * Byte Content
- * 0-1 msg_length - decoded by the record layer
- * 2 msg_type - s->init_msg points here
- * 3-4 version
- * 5-6 cipher_spec_length
- * 7-8 session_id_length
- * 9-10 challenge_length
- * ... ...
- */
-
- if (!PACKET_get_1(pkt, &mt)
- || mt != SSL2_MT_CLIENT_HELLO) {
- /*
- * Should never happen. We should have tested this in the record
- * layer in order to have determined that this is a SSLv2 record
- * in the first place
- */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
- if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_TOO_SHORT);
- goto err;
- }
-
- /* Parse the message and load client random. */
- if (clienthello->isv2) {
- /*
- * Handle an SSLv2 backwards compatible ClientHello
- * Note, this is only for SSLv3+ using the backward compatible format.
- * Real SSLv2 is not supported, and is rejected below.
- */
- unsigned int ciphersuite_len, session_id_len, challenge_len;
- PACKET challenge;
-
- if (!PACKET_get_net_2(pkt, &ciphersuite_len)
- || !PACKET_get_net_2(pkt, &session_id_len)
- || !PACKET_get_net_2(pkt, &challenge_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_RECORD_LENGTH_MISMATCH);
- goto err;
- }
-
- if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites,
- ciphersuite_len)
- || !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len)
- || !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
- /* No extensions. */
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_RECORD_LENGTH_MISMATCH);
- goto err;
- }
- clienthello->session_id_len = session_id_len;
-
- /* Load the client random and compression list. We use SSL3_RANDOM_SIZE
- * here rather than sizeof(clienthello->random) because that is the limit
- * for SSLv3 and it is fixed. It won't change even if
- * sizeof(clienthello->random) does.
- */
- challenge_len = challenge_len > SSL3_RANDOM_SIZE
- ? SSL3_RANDOM_SIZE : challenge_len;
- memset(clienthello->random, 0, SSL3_RANDOM_SIZE);
- if (!PACKET_copy_bytes(&challenge,
- clienthello->random + SSL3_RANDOM_SIZE -
- challenge_len, challenge_len)
- /* Advertise only null compression. */
- || !PACKET_buf_init(&compression, &null_compression, 1)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- PACKET_null_init(&clienthello->extensions);
- } else {
- /* Regular ClientHello. */
- if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE)
- || !PACKET_get_length_prefixed_1(pkt, &session_id)
- || !PACKET_copy_all(&session_id, clienthello->session_id,
- SSL_MAX_SSL_SESSION_ID_LENGTH,
- &clienthello->session_id_len)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (SSL_IS_DTLS(s)) {
- if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
- DTLS1_COOKIE_LENGTH,
- &clienthello->dtls_cookie_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /*
- * If we require cookies and this ClientHello doesn't contain one,
- * just return since we do not want to allocate any memory yet.
- * So check cookie length...
- */
- if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
- if (clienthello->dtls_cookie_len == 0) {
- OPENSSL_free(clienthello);
- return MSG_PROCESS_FINISHED_READING;
- }
- }
- }
-
- if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- /* Could be empty. */
- if (PACKET_remaining(pkt) == 0) {
- PACKET_null_init(&clienthello->extensions);
- } else {
- if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- }
- }
-
- if (!PACKET_copy_all(&compression, clienthello->compressions,
- MAX_COMPRESSIONS_SIZE,
- &clienthello->compressions_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Preserve the raw extensions PACKET for later use */
- extensions = clienthello->extensions;
- if (!tls_collect_extensions(s, &extensions, SSL_EXT_CLIENT_HELLO,
- &clienthello->pre_proc_exts,
- &clienthello->pre_proc_exts_len, 1)) {
- /* SSLfatal already been called */
- goto err;
- }
- s->clienthello = clienthello;
-
- return MSG_PROCESS_CONTINUE_PROCESSING;
-
- err:
- if (clienthello != NULL)
- OPENSSL_free(clienthello->pre_proc_exts);
- OPENSSL_free(clienthello);
-
- return MSG_PROCESS_ERROR;
-}
-
-static int tls_early_post_process_client_hello(SSL *s)
-{
- unsigned int j;
- int i, al = SSL_AD_INTERNAL_ERROR;
- int protverr;
- size_t loop;
- unsigned long id;
-#ifndef OPENSSL_NO_COMP
- SSL_COMP *comp = NULL;
-#endif
- const SSL_CIPHER *c;
- STACK_OF(SSL_CIPHER) *ciphers = NULL;
- STACK_OF(SSL_CIPHER) *scsvs = NULL;
- CLIENTHELLO_MSG *clienthello = s->clienthello;
- DOWNGRADE dgrd = DOWNGRADE_NONE;
-
- /* Finished parsing the ClientHello, now we can start processing it */
- /* Give the ClientHello callback a crack at things */
- if (s->ctx->client_hello_cb != NULL) {
- /* A failure in the ClientHello callback terminates the connection. */
- switch (s->ctx->client_hello_cb(s, &al, s->ctx->client_hello_cb_arg)) {
- case SSL_CLIENT_HELLO_SUCCESS:
- break;
- case SSL_CLIENT_HELLO_RETRY:
- s->rwstate = SSL_CLIENT_HELLO_CB;
- return -1;
- case SSL_CLIENT_HELLO_ERROR:
- default:
- SSLfatal(s, al,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_CALLBACK_FAILED);
- goto err;
- }
- }
-
- /* Set up the client_random */
- memcpy(s->s3->client_random, clienthello->random, SSL3_RANDOM_SIZE);
-
- /* Choose the version */
-
- if (clienthello->isv2) {
- if (clienthello->legacy_version == SSL2_VERSION
- || (clienthello->legacy_version & 0xff00)
- != (SSL3_VERSION_MAJOR << 8)) {
- /*
- * This is real SSLv2 or something completely unknown. We don't
- * support it.
- */
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_UNKNOWN_PROTOCOL);
- goto err;
- }
- /* SSLv3/TLS */
- s->client_version = clienthello->legacy_version;
- }
- /*
- * Do SSL/TLS version negotiation if applicable. For DTLS we just check
- * versions are potentially compatible. Version negotiation comes later.
- */
- if (!SSL_IS_DTLS(s)) {
- protverr = ssl_choose_server_version(s, clienthello, &dgrd);
- } else if (s->method->version != DTLS_ANY_VERSION &&
- DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) {
- protverr = SSL_R_VERSION_TOO_LOW;
- } else {
- protverr = 0;
- }
-
- if (protverr) {
- if (SSL_IS_FIRST_HANDSHAKE(s)) {
- /* like ssl3_get_record, send alert using remote version number */
- s->version = s->client_version = clienthello->legacy_version;
- }
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
- goto err;
- }
-
- /* TLSv1.3 specifies that a ClientHello must end on a record boundary */
- if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
- goto err;
- }
-
- if (SSL_IS_DTLS(s)) {
- /* Empty cookie was already handled above by returning early. */
- if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
- if (s->ctx->app_verify_cookie_cb != NULL) {
- if (s->ctx->app_verify_cookie_cb(s, clienthello->dtls_cookie,
- clienthello->dtls_cookie_len) == 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_COOKIE_MISMATCH);
- goto err;
- /* else cookie verification succeeded */
- }
- /* default verification */
- } else if (s->d1->cookie_len != clienthello->dtls_cookie_len
- || memcmp(clienthello->dtls_cookie, s->d1->cookie,
- s->d1->cookie_len) != 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_COOKIE_MISMATCH);
- goto err;
- }
- s->d1->cookie_verified = 1;
- }
- if (s->method->version == DTLS_ANY_VERSION) {
- protverr = ssl_choose_server_version(s, clienthello, &dgrd);
- if (protverr != 0) {
- s->version = s->client_version;
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
- goto err;
- }
- }
- }
-
- s->hit = 0;
-
- if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites,
- clienthello->isv2) ||
- !bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs,
- clienthello->isv2, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- s->s3->send_connection_binding = 0;
- /* Check what signalling cipher-suite values were received. */
- if (scsvs != NULL) {
- for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) {
- c = sk_SSL_CIPHER_value(scsvs, i);
- if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) {
- if (s->renegotiate) {
- /* SCSV is fatal if renegotiating */
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
- goto err;
- }
- s->s3->send_connection_binding = 1;
- } else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV &&
- !ssl_check_version_downgrade(s)) {
- /*
- * This SCSV indicates that the client previously tried
- * a higher version. We should fail if the current version
- * is an unexpected downgrade, as that indicates that the first
- * connection may have been tampered with in order to trigger
- * an insecure downgrade.
- */
- SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_INAPPROPRIATE_FALLBACK);
- goto err;
- }
- }
- }
-
- /* For TLSv1.3 we must select the ciphersuite *before* session resumption */
- if (SSL_IS_TLS13(s)) {
- const SSL_CIPHER *cipher =
- ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s));
-
- if (cipher == NULL) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NO_SHARED_CIPHER);
- goto err;
- }
- if (s->hello_retry_request == SSL_HRR_PENDING
- && (s->s3->tmp.new_cipher == NULL
- || s->s3->tmp.new_cipher->id != cipher->id)) {
- /*
- * A previous HRR picked a different ciphersuite to the one we
- * just selected. Something must have changed.
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_BAD_CIPHER);
- goto err;
- }
- s->s3->tmp.new_cipher = cipher;
- }
-
- /* We need to do this before getting the session */
- if (!tls_parse_extension(s, TLSEXT_IDX_extended_master_secret,
- SSL_EXT_CLIENT_HELLO,
- clienthello->pre_proc_exts, NULL, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /*
- * We don't allow resumption in a backwards compatible ClientHello.
- * TODO(openssl-team): in TLS1.1+, session_id MUST be empty.
- *
- * Versions before 0.9.7 always allow clients to resume sessions in
- * renegotiation. 0.9.7 and later allow this by default, but optionally
- * ignore resumption requests with flag
- * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather
- * than a change to default behavior so that applications relying on
- * this for security won't even compile against older library versions).
- * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to
- * request renegotiation but not a new session (s->new_session remains
- * unset): for servers, this essentially just means that the
- * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be
- * ignored.
- */
- if (clienthello->isv2 ||
- (s->new_session &&
- (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
- if (!ssl_get_new_session(s, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else {
- i = ssl_get_prev_session(s, clienthello);
- if (i == 1) {
- /* previous session */
- s->hit = 1;
- } else if (i == -1) {
- /* SSLfatal() already called */
- goto err;
- } else {
- /* i == 0 */
- if (!ssl_get_new_session(s, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
- }
- }
-
- if (SSL_IS_TLS13(s)) {
- memcpy(s->tmp_session_id, s->clienthello->session_id,
- s->clienthello->session_id_len);
- s->tmp_session_id_len = s->clienthello->session_id_len;
- }
-
- /*
- * If it is a hit, check that the cipher is in the list. In TLSv1.3 we check
- * ciphersuite compatibility with the session as part of resumption.
- */
- if (!SSL_IS_TLS13(s) && s->hit) {
- j = 0;
- id = s->session->cipher->id;
-
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "client sent %d ciphers\n", sk_SSL_CIPHER_num(ciphers));
-#endif
- for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
- c = sk_SSL_CIPHER_value(ciphers, i);
-#ifdef CIPHER_DEBUG
- fprintf(stderr, "client [%2d of %2d]:%s\n",
- i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c));
-#endif
- if (c->id == id) {
- j = 1;
- break;
- }
- }
- if (j == 0) {
- /*
- * we need to have the cipher in the cipher list if we are asked
- * to reuse it
- */
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_REQUIRED_CIPHER_MISSING);
- goto err;
- }
- }
-
- for (loop = 0; loop < clienthello->compressions_len; loop++) {
- if (clienthello->compressions[loop] == 0)
- break;
- }
-
- if (loop >= clienthello->compressions_len) {
- /* no compress */
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NO_COMPRESSION_SPECIFIED);
- goto err;
- }
-
-#ifndef OPENSSL_NO_EC
- if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
- ssl_check_for_safari(s, clienthello);
-#endif /* !OPENSSL_NO_EC */
-
- /* TLS extensions */
- if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO,
- clienthello->pre_proc_exts, NULL, 0, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /*
- * Check if we want to use external pre-shared secret for this handshake
- * for not reused session only. We need to generate server_random before
- * calling tls_session_secret_cb in order to allow SessionTicket
- * processing to use it in key derivation.
- */
- {
- unsigned char *pos;
- pos = s->s3->server_random;
- if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
- if (!s->hit
- && s->version >= TLS1_VERSION
- && !SSL_IS_TLS13(s)
- && !SSL_IS_DTLS(s)
- && s->ext.session_secret_cb) {
- const SSL_CIPHER *pref_cipher = NULL;
- /*
- * s->session->master_key_length is a size_t, but this is an int for
- * backwards compat reasons
- */
- int master_key_length;
-
- master_key_length = sizeof(s->session->master_key);
- if (s->ext.session_secret_cb(s, s->session->master_key,
- &master_key_length, ciphers,
- &pref_cipher,
- s->ext.session_secret_cb_arg)
- && master_key_length > 0) {
- s->session->master_key_length = master_key_length;
- s->hit = 1;
+ || !s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE))
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ break;
+
+ case TLS_ST_SW_CERT_REQ:
+ if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ }
+ break;
+
+ case TLS_ST_SW_KEY_UPDATE:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ if (!tls13_update_key(s, 1)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ break;
+
+ case TLS_ST_SW_SESSION_TICKET:
+ clear_sys_error();
+ if (SSL_IS_TLS13(s) && statem_flush(s) != 1) {
+ if (SSL_get_error(s, 0) == SSL_ERROR_SYSCALL
+ && conn_is_closed()) {
+ /*
+ * We ignore connection closed errors in TLSv1.3 when sending a
+ * NewSessionTicket and behave as if we were successful. This is
+ * so that we are still able to read data sent to us by a client
+ * that closes soon after the end of the handshake without
+ * waiting to read our post-handshake NewSessionTickets.
+ */
+ s->rwstate = SSL_NOTHING;
+ break;
+ }
+
+ return WORK_MORE_A;
+ }
+ break;
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+/*
+ * Get the message construction function and message type for sending from the
+ * server
+ *
+ * Valid return values are:
+ * 1: Success
+ * 0: Error
+ */
+int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
+ confunc_f *confunc, int *mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE,
+ SSL_R_BAD_HANDSHAKE_STATE);
+ return 0;
+
+ case TLS_ST_SW_CHANGE:
+ if (SSL_IS_DTLS(s))
+ *confunc = dtls_construct_change_cipher_spec;
+ else
+ *confunc = tls_construct_change_cipher_spec;
+ *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
+ break;
+
+ case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
+ *confunc = dtls_construct_hello_verify_request;
+ *mt = DTLS1_MT_HELLO_VERIFY_REQUEST;
+ break;
+
+ case TLS_ST_SW_HELLO_REQ:
+ /* No construction function needed */
+ *confunc = NULL;
+ *mt = SSL3_MT_HELLO_REQUEST;
+ break;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ *confunc = tls_construct_server_hello;
+ *mt = SSL3_MT_SERVER_HELLO;
+ break;
+
+ case TLS_ST_SW_CERT:
+ *confunc = tls_construct_server_certificate;
+ *mt = SSL3_MT_CERTIFICATE;
+ break;
+
+ case TLS_ST_SW_CERT_VRFY:
+ *confunc = tls_construct_cert_verify;
+ *mt = SSL3_MT_CERTIFICATE_VERIFY;
+ break;
+
+
+ case TLS_ST_SW_KEY_EXCH:
+ *confunc = tls_construct_server_key_exchange;
+ *mt = SSL3_MT_SERVER_KEY_EXCHANGE;
+ break;
+
+ case TLS_ST_SW_CERT_REQ:
+ *confunc = tls_construct_certificate_request;
+ *mt = SSL3_MT_CERTIFICATE_REQUEST;
+ break;
+
+ case TLS_ST_SW_SRVR_DONE:
+ *confunc = tls_construct_server_done;
+ *mt = SSL3_MT_SERVER_DONE;
+ break;
+
+ case TLS_ST_SW_SESSION_TICKET:
+ *confunc = tls_construct_new_session_ticket;
+ *mt = SSL3_MT_NEWSESSION_TICKET;
+ break;
+
+ case TLS_ST_SW_CERT_STATUS:
+ *confunc = tls_construct_cert_status;
+ *mt = SSL3_MT_CERTIFICATE_STATUS;
+ break;
+
+ case TLS_ST_SW_FINISHED:
+ *confunc = tls_construct_finished;
+ *mt = SSL3_MT_FINISHED;
+ break;
+
+ case TLS_ST_EARLY_DATA:
+ *confunc = NULL;
+ *mt = SSL3_MT_DUMMY;
+ break;
+
+ case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
+ *confunc = tls_construct_encrypted_extensions;
+ *mt = SSL3_MT_ENCRYPTED_EXTENSIONS;
+ break;
+
+ case TLS_ST_SW_KEY_UPDATE:
+ *confunc = tls_construct_key_update;
+ *mt = SSL3_MT_KEY_UPDATE;
+ break;
+ }
+
+ return 1;
+}
+
+/*
+ * Maximum size (excluding the Handshake header) of a ClientHello message,
+ * calculated as follows:
+ *
+ * 2 + # client_version
+ * 32 + # only valid length for random
+ * 1 + # length of session_id
+ * 32 + # maximum size for session_id
+ * 2 + # length of cipher suites
+ * 2^16-2 + # maximum length of cipher suites array
+ * 1 + # length of compression_methods
+ * 2^8-1 + # maximum length of compression methods
+ * 2 + # length of extensions
+ * 2^16-1 # maximum length of extensions
+ */
+#define CLIENT_HELLO_MAX_LENGTH 131396
+
+#define CLIENT_KEY_EXCH_MAX_LENGTH 2048
+#define NEXT_PROTO_MAX_LENGTH 514
+
+/*
+ * Returns the maximum allowed length for the current message that we are
+ * reading. Excludes the message header.
+ */
+size_t ossl_statem_server_max_message_size(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ return 0;
+
+ case TLS_ST_SR_CLNT_HELLO:
+ return CLIENT_HELLO_MAX_LENGTH;
+
+ case TLS_ST_SR_END_OF_EARLY_DATA:
+ return END_OF_EARLY_DATA_MAX_LENGTH;
+
+ case TLS_ST_SR_CERT:
+ return s->max_cert_list;
+
+ case TLS_ST_SR_KEY_EXCH:
+ return CLIENT_KEY_EXCH_MAX_LENGTH;
+
+ case TLS_ST_SR_CERT_VRFY:
+ return SSL3_RT_MAX_PLAIN_LENGTH;
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ case TLS_ST_SR_NEXT_PROTO:
+ return NEXT_PROTO_MAX_LENGTH;
+#endif
+
+ case TLS_ST_SR_CHANGE:
+ return CCS_MAX_LENGTH;
+
+ case TLS_ST_SR_FINISHED:
+ return FINISHED_MAX_LENGTH;
+
+ case TLS_ST_SR_KEY_UPDATE:
+ return KEY_UPDATE_MAX_LENGTH;
+ }
+}
+
+/*
+ * Process a message that the server has received from the client.
+ */
+MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE,
+ ERR_R_INTERNAL_ERROR);
+ return MSG_PROCESS_ERROR;
+
+ case TLS_ST_SR_CLNT_HELLO:
+ return tls_process_client_hello(s, pkt);
+
+ case TLS_ST_SR_END_OF_EARLY_DATA:
+ return tls_process_end_of_early_data(s, pkt);
+
+ case TLS_ST_SR_CERT:
+ return tls_process_client_certificate(s, pkt);
+
+ case TLS_ST_SR_KEY_EXCH:
+ return tls_process_client_key_exchange(s, pkt);
+
+ case TLS_ST_SR_CERT_VRFY:
+ return tls_process_cert_verify(s, pkt);
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ case TLS_ST_SR_NEXT_PROTO:
+ return tls_process_next_proto(s, pkt);
+#endif
+
+ case TLS_ST_SR_CHANGE:
+ return tls_process_change_cipher_spec(s, pkt);
+
+ case TLS_ST_SR_FINISHED:
+ return tls_process_finished(s, pkt);
+
+ case TLS_ST_SR_KEY_UPDATE:
+ return tls_process_key_update(s, pkt);
+
+ }
+}
+
+/*
+ * Perform any further processing required following the receipt of a message
+ * from the client
+ */
+WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+
+ case TLS_ST_SR_CLNT_HELLO:
+ return tls_post_process_client_hello(s, wst);
+
+ case TLS_ST_SR_KEY_EXCH:
+ return tls_post_process_client_key_exchange(s, wst);
+ }
+}
+
+#ifndef OPENSSL_NO_SRP
+/* Returns 1 on success, 0 for retryable error, -1 for fatal error */
+static int ssl_check_srp_ext_ClientHello(SSL *s)
+{
+ int ret;
+ int al = SSL_AD_UNRECOGNIZED_NAME;
+
+ if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
+ (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
+ if (s->srp_ctx.login == NULL) {
+ /*
+ * RFC 5054 says SHOULD reject, we do so if There is no srp
+ * login name
+ */
+ SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
+ SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ return -1;
+ } else {
+ ret = SSL_srp_server_param_with_username(s, &al);
+ if (ret < 0)
+ return 0;
+ if (ret == SSL3_AL_FATAL) {
+ SSLfatal(s, al, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
+ al == SSL_AD_UNKNOWN_PSK_IDENTITY
+ ? SSL_R_PSK_IDENTITY_NOT_FOUND
+ : SSL_R_CLIENTHELLO_TLSEXT);
+ return -1;
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
+ size_t cookie_len)
+{
+ /* Always use DTLS 1.0 version: see RFC 6347 */
+ if (!WPACKET_put_bytes_u16(pkt, DTLS1_VERSION)
+ || !WPACKET_sub_memcpy_u8(pkt, cookie, cookie_len))
+ return 0;
+
+ return 1;
+}
+
+int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
+{
+ unsigned int cookie_leni;
+ if (s->ctx->app_gen_cookie_cb == NULL ||
+ s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
+ &cookie_leni) == 0 ||
+ cookie_leni > 255) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
+ SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+ return 0;
+ }
+ s->d1->cookie_len = cookie_leni;
+
+ if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
+ s->d1->cookie_len)) {
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ 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
+ * signature_algorithms (for TLSv1.2 only)
+ *
+ * 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)
+{
+ 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;
+ unsigned int type;
+ PACKET sni, tmppkt;
+ size_t ext_len;
+
+ 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 */
+
+MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
+{
+ /* |cookie| will only be initialized for DTLS. */
+ PACKET session_id, compression, extensions, cookie;
+ static const unsigned char null_compression = 0;
+ CLIENTHELLO_MSG *clienthello = NULL;
+
+ /* Check if this is actually an unexpected renegotiation ClientHello */
+ if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
+ if (!ossl_assert(!SSL_IS_TLS13(s))) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0
+ || (!s->s3->send_connection_binding
+ && (s->options
+ & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) {
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
+ return MSG_PROCESS_FINISHED_READING;
+ }
+ s->renegotiate = 1;
+ s->new_session = 1;
+ }
+
+ clienthello = OPENSSL_zalloc(sizeof(*clienthello));
+ if (clienthello == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure.
+ */
+ clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer);
+ PACKET_null_init(&cookie);
+
+ if (clienthello->isv2) {
+ unsigned int mt;
+
+ if (!SSL_IS_FIRST_HANDSHAKE(s)
+ || s->hello_retry_request != SSL_HRR_NONE) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
+ /*-
+ * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
+ * header is sent directly on the wire, not wrapped as a TLS
+ * record. Our record layer just processes the message length and passes
+ * the rest right through. Its format is:
+ * Byte Content
+ * 0-1 msg_length - decoded by the record layer
+ * 2 msg_type - s->init_msg points here
+ * 3-4 version
+ * 5-6 cipher_spec_length
+ * 7-8 session_id_length
+ * 9-10 challenge_length
+ * ... ...
+ */
+
+ if (!PACKET_get_1(pkt, &mt)
+ || mt != SSL2_MT_CLIENT_HELLO) {
+ /*
+ * Should never happen. We should have tested this in the record
+ * layer in order to have determined that this is a SSLv2 record
+ * in the first place
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto err;
+ }
+
+ /* Parse the message and load client random. */
+ if (clienthello->isv2) {
+ /*
+ * Handle an SSLv2 backwards compatible ClientHello
+ * Note, this is only for SSLv3+ using the backward compatible format.
+ * Real SSLv2 is not supported, and is rejected below.
+ */
+ unsigned int ciphersuite_len, session_id_len, challenge_len;
+ PACKET challenge;
+
+ if (!PACKET_get_net_2(pkt, &ciphersuite_len)
+ || !PACKET_get_net_2(pkt, &session_id_len)
+ || !PACKET_get_net_2(pkt, &challenge_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_RECORD_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites,
+ ciphersuite_len)
+ || !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len)
+ || !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
+ /* No extensions. */
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_RECORD_LENGTH_MISMATCH);
+ goto err;
+ }
+ clienthello->session_id_len = session_id_len;
+
+ /* Load the client random and compression list. We use SSL3_RANDOM_SIZE
+ * here rather than sizeof(clienthello->random) because that is the limit
+ * for SSLv3 and it is fixed. It won't change even if
+ * sizeof(clienthello->random) does.
+ */
+ challenge_len = challenge_len > SSL3_RANDOM_SIZE
+ ? SSL3_RANDOM_SIZE : challenge_len;
+ memset(clienthello->random, 0, SSL3_RANDOM_SIZE);
+ if (!PACKET_copy_bytes(&challenge,
+ clienthello->random + SSL3_RANDOM_SIZE -
+ challenge_len, challenge_len)
+ /* Advertise only null compression. */
+ || !PACKET_buf_init(&compression, &null_compression, 1)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ PACKET_null_init(&clienthello->extensions);
+ } else {
+ /* Regular ClientHello. */
+ if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE)
+ || !PACKET_get_length_prefixed_1(pkt, &session_id)
+ || !PACKET_copy_all(&session_id, clienthello->session_id,
+ SSL_MAX_SSL_SESSION_ID_LENGTH,
+ &clienthello->session_id_len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
+ DTLS1_COOKIE_LENGTH,
+ &clienthello->dtls_cookie_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ /*
+ * If we require cookies and this ClientHello doesn't contain one,
+ * just return since we do not want to allocate any memory yet.
+ * So check cookie length...
+ */
+ if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
+ if (clienthello->dtls_cookie_len == 0) {
+ OPENSSL_free(clienthello);
+ return MSG_PROCESS_FINISHED_READING;
+ }
+ }
+ }
+
+ if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ /* Could be empty. */
+ if (PACKET_remaining(pkt) == 0) {
+ PACKET_null_init(&clienthello->extensions);
+ } else {
+ if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ }
+ }
+
+ if (!PACKET_copy_all(&compression, clienthello->compressions,
+ MAX_COMPRESSIONS_SIZE,
+ &clienthello->compressions_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Preserve the raw extensions PACKET for later use */
+ extensions = clienthello->extensions;
+ if (!tls_collect_extensions(s, &extensions, SSL_EXT_CLIENT_HELLO,
+ &clienthello->pre_proc_exts,
+ &clienthello->pre_proc_exts_len, 1)) {
+ /* SSLfatal already been called */
+ goto err;
+ }
+ s->clienthello = clienthello;
+
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+
+ err:
+ if (clienthello != NULL)
+ OPENSSL_free(clienthello->pre_proc_exts);
+ OPENSSL_free(clienthello);
+
+ return MSG_PROCESS_ERROR;
+}
+
+static int tls_early_post_process_client_hello(SSL *s)
+{
+ unsigned int j;
+ int i, al = SSL_AD_INTERNAL_ERROR;
+ int protverr;
+ size_t loop;
+ unsigned long id;
+#ifndef OPENSSL_NO_COMP
+ SSL_COMP *comp = NULL;
+#endif
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) *ciphers = NULL;
+ STACK_OF(SSL_CIPHER) *scsvs = NULL;
+ CLIENTHELLO_MSG *clienthello = s->clienthello;
+ DOWNGRADE dgrd = DOWNGRADE_NONE;
+
+ /* Finished parsing the ClientHello, now we can start processing it */
+ /* Give the ClientHello callback a crack at things */
+ if (s->ctx->client_hello_cb != NULL) {
+ /* A failure in the ClientHello callback terminates the connection. */
+ switch (s->ctx->client_hello_cb(s, &al, s->ctx->client_hello_cb_arg)) {
+ case SSL_CLIENT_HELLO_SUCCESS:
+ break;
+ case SSL_CLIENT_HELLO_RETRY:
+ s->rwstate = SSL_CLIENT_HELLO_CB;
+ return -1;
+ case SSL_CLIENT_HELLO_ERROR:
+ default:
+ SSLfatal(s, al,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_CALLBACK_FAILED);
+ goto err;
+ }
+ }
+
+ /* Set up the client_random */
+ memcpy(s->s3->client_random, clienthello->random, SSL3_RANDOM_SIZE);
+
+ /* Choose the version */
+
+ if (clienthello->isv2) {
+ if (clienthello->legacy_version == SSL2_VERSION
+ || (clienthello->legacy_version & 0xff00)
+ != (SSL3_VERSION_MAJOR << 8)) {
+ /*
+ * This is real SSLv2 or something completely unknown. We don't
+ * support it.
+ */
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ }
+ /* SSLv3/TLS */
+ s->client_version = clienthello->legacy_version;
+ }
+ /*
+ * Do SSL/TLS version negotiation if applicable. For DTLS we just check
+ * versions are potentially compatible. Version negotiation comes later.
+ */
+ if (!SSL_IS_DTLS(s)) {
+ protverr = ssl_choose_server_version(s, clienthello, &dgrd);
+ } else if (s->method->version != DTLS_ANY_VERSION &&
+ DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) {
+ protverr = SSL_R_VERSION_TOO_LOW;
+ } else {
+ protverr = 0;
+ }
+
+ if (protverr) {
+ if (SSL_IS_FIRST_HANDSHAKE(s)) {
+ /* like ssl3_get_record, send alert using remote version number */
+ s->version = s->client_version = clienthello->legacy_version;
+ }
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
+ goto err;
+ }
+
+ /* TLSv1.3 specifies that a ClientHello must end on a record boundary */
+ if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_NOT_ON_RECORD_BOUNDARY);
+ goto err;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ /* Empty cookie was already handled above by returning early. */
+ if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
+ if (s->ctx->app_verify_cookie_cb != NULL) {
+ if (s->ctx->app_verify_cookie_cb(s, clienthello->dtls_cookie,
+ clienthello->dtls_cookie_len) == 0) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_COOKIE_MISMATCH);
+ goto err;
+ /* else cookie verification succeeded */
+ }
+ /* default verification */
+ } else if (s->d1->cookie_len != clienthello->dtls_cookie_len
+ || memcmp(clienthello->dtls_cookie, s->d1->cookie,
+ s->d1->cookie_len) != 0) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_COOKIE_MISMATCH);
+ goto err;
+ }
+ s->d1->cookie_verified = 1;
+ }
+ if (s->method->version == DTLS_ANY_VERSION) {
+ protverr = ssl_choose_server_version(s, clienthello, &dgrd);
+ if (protverr != 0) {
+ s->version = s->client_version;
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
+ goto err;
+ }
+ }
+ }
+
+ s->hit = 0;
+
+ if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites,
+ clienthello->isv2) ||
+ !bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs,
+ clienthello->isv2, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ s->s3->send_connection_binding = 0;
+ /* Check what signalling cipher-suite values were received. */
+ if (scsvs != NULL) {
+ for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) {
+ c = sk_SSL_CIPHER_value(scsvs, i);
+ if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) {
+ if (s->renegotiate) {
+ /* SCSV is fatal if renegotiating */
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
+ goto err;
+ }
+ s->s3->send_connection_binding = 1;
+ } else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV &&
+ !ssl_check_version_downgrade(s)) {
+ /*
+ * This SCSV indicates that the client previously tried
+ * a higher version. We should fail if the current version
+ * is an unexpected downgrade, as that indicates that the first
+ * connection may have been tampered with in order to trigger
+ * an insecure downgrade.
+ */
+ SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_INAPPROPRIATE_FALLBACK);
+ goto err;
+ }
+ }
+ }
+
+ /* For TLSv1.3 we must select the ciphersuite *before* session resumption */
+ if (SSL_IS_TLS13(s)) {
+ const SSL_CIPHER *cipher =
+ ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s));
+
+ if (cipher == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_NO_SHARED_CIPHER);
+ goto err;
+ }
+ if (s->hello_retry_request == SSL_HRR_PENDING
+ && (s->s3->tmp.new_cipher == NULL
+ || s->s3->tmp.new_cipher->id != cipher->id)) {
+ /*
+ * A previous HRR picked a different ciphersuite to the one we
+ * just selected. Something must have changed.
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_BAD_CIPHER);
+ goto err;
+ }
+ s->s3->tmp.new_cipher = cipher;
+ }
+
+ /* We need to do this before getting the session */
+ if (!tls_parse_extension(s, TLSEXT_IDX_extended_master_secret,
+ SSL_EXT_CLIENT_HELLO,
+ clienthello->pre_proc_exts, NULL, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /*
+ * We don't allow resumption in a backwards compatible ClientHello.
+ * TODO(openssl-team): in TLS1.1+, session_id MUST be empty.
+ *
+ * Versions before 0.9.7 always allow clients to resume sessions in
+ * renegotiation. 0.9.7 and later allow this by default, but optionally
+ * ignore resumption requests with flag
+ * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather
+ * than a change to default behavior so that applications relying on
+ * this for security won't even compile against older library versions).
+ * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to
+ * request renegotiation but not a new session (s->new_session remains
+ * unset): for servers, this essentially just means that the
+ * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be
+ * ignored.
+ */
+ if (clienthello->isv2 ||
+ (s->new_session &&
+ (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
+ if (!ssl_get_new_session(s, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else {
+ i = ssl_get_prev_session(s, clienthello);
+ if (i == 1) {
+ /* previous session */
+ s->hit = 1;
+ } else if (i == -1) {
+ /* SSLfatal() already called */
+ goto err;
+ } else {
+ /* i == 0 */
+ if (!ssl_get_new_session(s, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+ }
+
+ if (SSL_IS_TLS13(s)) {
+ memcpy(s->tmp_session_id, s->clienthello->session_id,
+ s->clienthello->session_id_len);
+ s->tmp_session_id_len = s->clienthello->session_id_len;
+ }
+
+ /*
+ * If it is a hit, check that the cipher is in the list. In TLSv1.3 we check
+ * ciphersuite compatibility with the session as part of resumption.
+ */
+ if (!SSL_IS_TLS13(s) && s->hit) {
+ j = 0;
+ id = s->session->cipher->id;
+
+#ifdef CIPHER_DEBUG
+ fprintf(stderr, "client sent %d ciphers\n", sk_SSL_CIPHER_num(ciphers));
+#endif
+ for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
+ c = sk_SSL_CIPHER_value(ciphers, i);
+#ifdef CIPHER_DEBUG
+ fprintf(stderr, "client [%2d of %2d]:%s\n",
+ i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c));
+#endif
+ if (c->id == id) {
+ j = 1;
+ break;
+ }
+ }
+ if (j == 0) {
+ /*
+ * we need to have the cipher in the cipher list if we are asked
+ * to reuse it
+ */
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_REQUIRED_CIPHER_MISSING);
+ goto err;
+ }
+ }
+
+ for (loop = 0; loop < clienthello->compressions_len; loop++) {
+ if (clienthello->compressions[loop] == 0)
+ break;
+ }
+
+ if (loop >= clienthello->compressions_len) {
+ /* no compress */
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_NO_COMPRESSION_SPECIFIED);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_EC
+ if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
+ ssl_check_for_safari(s, clienthello);
+#endif /* !OPENSSL_NO_EC */
+
+ /* TLS extensions */
+ if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO,
+ clienthello->pre_proc_exts, NULL, 0, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /*
+ * Check if we want to use external pre-shared secret for this handshake
+ * for not reused session only. We need to generate server_random before
+ * calling tls_session_secret_cb in order to allow SessionTicket
+ * processing to use it in key derivation.
+ */
+ {
+ unsigned char *pos;
+ pos = s->s3->server_random;
+ if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (!s->hit
+ && s->version >= TLS1_VERSION
+ && !SSL_IS_TLS13(s)
+ && !SSL_IS_DTLS(s)
+ && s->ext.session_secret_cb) {
+ const SSL_CIPHER *pref_cipher = NULL;
+ /*
+ * s->session->master_key_length is a size_t, but this is an int for
+ * backwards compat reasons
+ */
+ int master_key_length;
+
+ master_key_length = sizeof(s->session->master_key);
+ if (s->ext.session_secret_cb(s, s->session->master_key,
+ &master_key_length, ciphers,
+ &pref_cipher,
+ s->ext.session_secret_cb_arg)
+ && master_key_length > 0) {
+ s->session->master_key_length = master_key_length;
+ s->hit = 1;
s->peer_ciphers = ciphers;
- s->session->verify_result = X509_V_OK;
-
- ciphers = NULL;
-
- /* check if some cipher was preferred by call back */
- if (pref_cipher == NULL)
+ s->session->verify_result = X509_V_OK;
+
+ ciphers = NULL;
+
+ /* check if some cipher was preferred by call back */
+ if (pref_cipher == NULL)
pref_cipher = ssl3_choose_cipher(s, s->peer_ciphers,
- SSL_get_ciphers(s));
- if (pref_cipher == NULL) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NO_SHARED_CIPHER);
- goto err;
- }
-
- s->session->cipher = pref_cipher;
- sk_SSL_CIPHER_free(s->cipher_list);
+ SSL_get_ciphers(s));
+ if (pref_cipher == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_NO_SHARED_CIPHER);
+ goto err;
+ }
+
+ s->session->cipher = pref_cipher;
+ sk_SSL_CIPHER_free(s->cipher_list);
s->cipher_list = sk_SSL_CIPHER_dup(s->peer_ciphers);
- sk_SSL_CIPHER_free(s->cipher_list_by_id);
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->peer_ciphers);
- }
- }
-
- /*
- * Worst case, we will use the NULL compression, but if we have other
- * options, we will now look for them. We have complen-1 compression
- * algorithms from the client, starting at q.
- */
- s->s3->tmp.new_compression = NULL;
- if (SSL_IS_TLS13(s)) {
- /*
- * We already checked above that the NULL compression method appears in
- * the list. Now we check there aren't any others (which is illegal in
- * a TLSv1.3 ClientHello.
- */
- if (clienthello->compressions_len != 1) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_INVALID_COMPRESSION_ALGORITHM);
- goto err;
- }
- }
-#ifndef OPENSSL_NO_COMP
- /* This only happens if we have a cache hit */
- else if (s->session->compress_meth != 0) {
- int m, comp_id = s->session->compress_meth;
- unsigned int k;
- /* Perform sanity checks on resumed compression algorithm */
- /* Can't disable compression */
- if (!ssl_allow_compression(s)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_INCONSISTENT_COMPRESSION);
- goto err;
- }
- /* Look for resumed compression method */
- for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) {
- comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
- if (comp_id == comp->id) {
- s->s3->tmp.new_compression = comp;
- break;
- }
- }
- if (s->s3->tmp.new_compression == NULL) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_INVALID_COMPRESSION_ALGORITHM);
- goto err;
- }
- /* Look for resumed method in compression list */
- for (k = 0; k < clienthello->compressions_len; k++) {
- if (clienthello->compressions[k] == comp_id)
- break;
- }
- if (k >= clienthello->compressions_len) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
- goto err;
- }
- } else if (s->hit) {
- comp = NULL;
- } else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
- /* See if we have a match */
- int m, nn, v, done = 0;
- unsigned int o;
-
- nn = sk_SSL_COMP_num(s->ctx->comp_methods);
- for (m = 0; m < nn; m++) {
- comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
- v = comp->id;
- for (o = 0; o < clienthello->compressions_len; o++) {
- if (v == clienthello->compressions[o]) {
- done = 1;
- break;
- }
- }
- if (done)
- break;
- }
- if (done)
- s->s3->tmp.new_compression = comp;
- else
- comp = NULL;
- }
-#else
- /*
- * If compression is disabled we'd better not try to resume a session
- * using compression.
- */
- if (s->session->compress_meth != 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- SSL_R_INCONSISTENT_COMPRESSION);
- goto err;
- }
-#endif
-
- /*
+ }
+ }
+
+ /*
+ * Worst case, we will use the NULL compression, but if we have other
+ * options, we will now look for them. We have complen-1 compression
+ * algorithms from the client, starting at q.
+ */
+ s->s3->tmp.new_compression = NULL;
+ if (SSL_IS_TLS13(s)) {
+ /*
+ * We already checked above that the NULL compression method appears in
+ * the list. Now we check there aren't any others (which is illegal in
+ * a TLSv1.3 ClientHello.
+ */
+ if (clienthello->compressions_len != 1) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_INVALID_COMPRESSION_ALGORITHM);
+ goto err;
+ }
+ }
+#ifndef OPENSSL_NO_COMP
+ /* This only happens if we have a cache hit */
+ else if (s->session->compress_meth != 0) {
+ int m, comp_id = s->session->compress_meth;
+ unsigned int k;
+ /* Perform sanity checks on resumed compression algorithm */
+ /* Can't disable compression */
+ if (!ssl_allow_compression(s)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_INCONSISTENT_COMPRESSION);
+ goto err;
+ }
+ /* Look for resumed compression method */
+ for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) {
+ comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
+ if (comp_id == comp->id) {
+ s->s3->tmp.new_compression = comp;
+ break;
+ }
+ }
+ if (s->s3->tmp.new_compression == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_INVALID_COMPRESSION_ALGORITHM);
+ goto err;
+ }
+ /* Look for resumed method in compression list */
+ for (k = 0; k < clienthello->compressions_len; k++) {
+ if (clienthello->compressions[k] == comp_id)
+ break;
+ }
+ if (k >= clienthello->compressions_len) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
+ goto err;
+ }
+ } else if (s->hit) {
+ comp = NULL;
+ } else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
+ /* See if we have a match */
+ int m, nn, v, done = 0;
+ unsigned int o;
+
+ nn = sk_SSL_COMP_num(s->ctx->comp_methods);
+ for (m = 0; m < nn; m++) {
+ comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
+ v = comp->id;
+ for (o = 0; o < clienthello->compressions_len; o++) {
+ if (v == clienthello->compressions[o]) {
+ done = 1;
+ break;
+ }
+ }
+ if (done)
+ break;
+ }
+ if (done)
+ s->s3->tmp.new_compression = comp;
+ else
+ comp = NULL;
+ }
+#else
+ /*
+ * If compression is disabled we'd better not try to resume a session
+ * using compression.
+ */
+ if (s->session->compress_meth != 0) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_INCONSISTENT_COMPRESSION);
+ goto err;
+ }
+#endif
+
+ /*
* Given s->peer_ciphers and SSL_get_ciphers, we must pick a cipher
- */
-
- if (!s->hit || SSL_IS_TLS13(s)) {
+ */
+
+ if (!s->hit || SSL_IS_TLS13(s)) {
sk_SSL_CIPHER_free(s->peer_ciphers);
s->peer_ciphers = ciphers;
- if (ciphers == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- ciphers = NULL;
- }
-
- if (!s->hit) {
-#ifdef OPENSSL_NO_COMP
- s->session->compress_meth = 0;
-#else
- s->session->compress_meth = (comp == NULL) ? 0 : comp->id;
-#endif
+ if (ciphers == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ ciphers = NULL;
+ }
+
+ if (!s->hit) {
+#ifdef OPENSSL_NO_COMP
+ s->session->compress_meth = 0;
+#else
+ s->session->compress_meth = (comp == NULL) ? 0 : comp->id;
+#endif
if (!tls1_set_server_sigalgs(s)) {
/* SSLfatal() already called */
goto err;
}
- }
-
- sk_SSL_CIPHER_free(ciphers);
- sk_SSL_CIPHER_free(scsvs);
- OPENSSL_free(clienthello->pre_proc_exts);
- OPENSSL_free(s->clienthello);
- s->clienthello = NULL;
- return 1;
- err:
- sk_SSL_CIPHER_free(ciphers);
- sk_SSL_CIPHER_free(scsvs);
- OPENSSL_free(clienthello->pre_proc_exts);
- OPENSSL_free(s->clienthello);
- s->clienthello = NULL;
-
- return 0;
-}
-
-/*
- * Call the status request callback if needed. Upon success, returns 1.
- * Upon failure, returns 0.
- */
-static int tls_handle_status_request(SSL *s)
-{
- s->ext.status_expected = 0;
-
- /*
- * If status request then ask callback what to do. Note: this must be
- * called after servername callbacks in case the certificate has changed,
- * and must be called after the cipher has been chosen because this may
- * influence which certificate is sent
- */
- if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && s->ctx != NULL
- && s->ctx->ext.status_cb != NULL) {
- int ret;
-
- /* If no certificate can't return certificate status */
- if (s->s3->tmp.cert != NULL) {
- /*
- * Set current certificate to one we will use so SSL_get_certificate
- * et al can pick it up.
- */
- s->cert->key = s->s3->tmp.cert;
- ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
- switch (ret) {
- /* We don't want to send a status request response */
- case SSL_TLSEXT_ERR_NOACK:
- s->ext.status_expected = 0;
- break;
- /* status request response should be sent */
- case SSL_TLSEXT_ERR_OK:
- if (s->ext.ocsp.resp)
- s->ext.status_expected = 1;
- break;
- /* something bad happened */
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- default:
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_HANDLE_STATUS_REQUEST,
- SSL_R_CLIENTHELLO_TLSEXT);
- return 0;
- }
- }
- }
-
- return 1;
-}
-
-/*
- * Call the alpn_select callback if needed. Upon success, returns 1.
- * Upon failure, returns 0.
- */
-int tls_handle_alpn(SSL *s)
-{
- const unsigned char *selected = NULL;
- unsigned char selected_len = 0;
-
- if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
- int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len,
- s->s3->alpn_proposed,
- (unsigned int)s->s3->alpn_proposed_len,
- s->ctx->ext.alpn_select_cb_arg);
-
- if (r == SSL_TLSEXT_ERR_OK) {
- OPENSSL_free(s->s3->alpn_selected);
- s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
- if (s->s3->alpn_selected == NULL) {
+ }
+
+ sk_SSL_CIPHER_free(ciphers);
+ sk_SSL_CIPHER_free(scsvs);
+ OPENSSL_free(clienthello->pre_proc_exts);
+ OPENSSL_free(s->clienthello);
+ s->clienthello = NULL;
+ return 1;
+ err:
+ sk_SSL_CIPHER_free(ciphers);
+ sk_SSL_CIPHER_free(scsvs);
+ OPENSSL_free(clienthello->pre_proc_exts);
+ OPENSSL_free(s->clienthello);
+ s->clienthello = NULL;
+
+ return 0;
+}
+
+/*
+ * Call the status request callback if needed. Upon success, returns 1.
+ * Upon failure, returns 0.
+ */
+static int tls_handle_status_request(SSL *s)
+{
+ s->ext.status_expected = 0;
+
+ /*
+ * If status request then ask callback what to do. Note: this must be
+ * called after servername callbacks in case the certificate has changed,
+ * and must be called after the cipher has been chosen because this may
+ * influence which certificate is sent
+ */
+ if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && s->ctx != NULL
+ && s->ctx->ext.status_cb != NULL) {
+ int ret;
+
+ /* If no certificate can't return certificate status */
+ if (s->s3->tmp.cert != NULL) {
+ /*
+ * Set current certificate to one we will use so SSL_get_certificate
+ * et al can pick it up.
+ */
+ s->cert->key = s->s3->tmp.cert;
+ ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
+ switch (ret) {
+ /* We don't want to send a status request response */
+ case SSL_TLSEXT_ERR_NOACK:
+ s->ext.status_expected = 0;
+ break;
+ /* status request response should be sent */
+ case SSL_TLSEXT_ERR_OK:
+ if (s->ext.ocsp.resp)
+ s->ext.status_expected = 1;
+ break;
+ /* something bad happened */
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ default:
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_HANDLE_STATUS_REQUEST,
+ SSL_R_CLIENTHELLO_TLSEXT);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Call the alpn_select callback if needed. Upon success, returns 1.
+ * Upon failure, returns 0.
+ */
+int tls_handle_alpn(SSL *s)
+{
+ const unsigned char *selected = NULL;
+ unsigned char selected_len = 0;
+
+ if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
+ int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len,
+ s->s3->alpn_proposed,
+ (unsigned int)s->s3->alpn_proposed_len,
+ s->ctx->ext.alpn_select_cb_arg);
+
+ if (r == SSL_TLSEXT_ERR_OK) {
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
+ if (s->s3->alpn_selected == NULL) {
s->s3->alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->s3->alpn_selected_len = selected_len;
-#ifndef OPENSSL_NO_NEXTPROTONEG
- /* ALPN takes precedence over NPN. */
- s->s3->npn_seen = 0;
-#endif
-
- /* Check ALPN is consistent with session */
- if (s->session->ext.alpn_selected == NULL
- || selected_len != s->session->ext.alpn_selected_len
- || memcmp(selected, s->session->ext.alpn_selected,
- selected_len) != 0) {
- /* Not consistent so can't be used for early_data */
- s->ext.early_data_ok = 0;
-
- if (!s->hit) {
- /*
- * This is a new session and so alpn_selected should have
- * been initialised to NULL. We should update it with the
- * selected ALPN.
- */
- if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_HANDLE_ALPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->session->ext.alpn_selected = OPENSSL_memdup(selected,
- selected_len);
- if (s->session->ext.alpn_selected == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_HANDLE_ALPN,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->session->ext.alpn_selected_len = selected_len;
- }
- }
-
- return 1;
- } else if (r != SSL_TLSEXT_ERR_NOACK) {
- SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN,
- SSL_R_NO_APPLICATION_PROTOCOL);
- return 0;
- }
- /*
- * If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was
- * present.
- */
- }
-
- /* Check ALPN is consistent with session */
- if (s->session->ext.alpn_selected != NULL) {
- /* Not consistent so can't be used for early_data */
- s->ext.early_data_ok = 0;
- }
-
- return 1;
-}
-
-WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
-{
- const SSL_CIPHER *cipher;
-
- if (wst == WORK_MORE_A) {
- int rv = tls_early_post_process_client_hello(s);
- if (rv == 0) {
- /* SSLfatal() was already called */
- goto err;
- }
- if (rv < 0)
- return WORK_MORE_A;
- wst = WORK_MORE_B;
- }
- if (wst == WORK_MORE_B) {
- if (!s->hit || SSL_IS_TLS13(s)) {
- /* Let cert callback update server certificates if required */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->s3->alpn_selected_len = selected_len;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ /* ALPN takes precedence over NPN. */
+ s->s3->npn_seen = 0;
+#endif
+
+ /* Check ALPN is consistent with session */
+ if (s->session->ext.alpn_selected == NULL
+ || selected_len != s->session->ext.alpn_selected_len
+ || memcmp(selected, s->session->ext.alpn_selected,
+ selected_len) != 0) {
+ /* Not consistent so can't be used for early_data */
+ s->ext.early_data_ok = 0;
+
+ if (!s->hit) {
+ /*
+ * This is a new session and so alpn_selected should have
+ * been initialised to NULL. We should update it with the
+ * selected ALPN.
+ */
+ if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_HANDLE_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->session->ext.alpn_selected = OPENSSL_memdup(selected,
+ selected_len);
+ if (s->session->ext.alpn_selected == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_HANDLE_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->session->ext.alpn_selected_len = selected_len;
+ }
+ }
+
+ return 1;
+ } else if (r != SSL_TLSEXT_ERR_NOACK) {
+ SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN,
+ SSL_R_NO_APPLICATION_PROTOCOL);
+ return 0;
+ }
+ /*
+ * If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was
+ * present.
+ */
+ }
+
+ /* Check ALPN is consistent with session */
+ if (s->session->ext.alpn_selected != NULL) {
+ /* Not consistent so can't be used for early_data */
+ s->ext.early_data_ok = 0;
+ }
+
+ return 1;
+}
+
+WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
+{
+ const SSL_CIPHER *cipher;
+
+ if (wst == WORK_MORE_A) {
+ int rv = tls_early_post_process_client_hello(s);
+ if (rv == 0) {
+ /* SSLfatal() was already called */
+ goto err;
+ }
+ if (rv < 0)
+ return WORK_MORE_A;
+ wst = WORK_MORE_B;
+ }
+ if (wst == WORK_MORE_B) {
+ if (!s->hit || SSL_IS_TLS13(s)) {
+ /* Let cert callback update server certificates if required */
if (!s->hit && s->cert->cert_cb != NULL) {
int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
if (rv == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
SSL_R_CERT_CB_ERROR);
- goto err;
- }
+ goto err;
+ }
if (rv < 0) {
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_B;
}
s->rwstate = SSL_NOTHING;
- }
-
- /* In TLSv1.3 we selected the ciphersuite before resumption */
- if (!SSL_IS_TLS13(s)) {
- cipher =
+ }
+
+ /* In TLSv1.3 we selected the ciphersuite before resumption */
+ if (!SSL_IS_TLS13(s)) {
+ cipher =
ssl3_choose_cipher(s, s->peer_ciphers, SSL_get_ciphers(s));
-
- if (cipher == NULL) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
- SSL_R_NO_SHARED_CIPHER);
- goto err;
- }
- s->s3->tmp.new_cipher = cipher;
- }
- if (!s->hit) {
- if (!tls_choose_sigalg(s, 1)) {
- /* SSLfatal already called */
- goto err;
- }
- /* check whether we should disable session resumption */
- if (s->not_resumable_session_cb != NULL)
- s->session->not_resumable =
- s->not_resumable_session_cb(s,
- ((s->s3->tmp.new_cipher->algorithm_mkey
- & (SSL_kDHE | SSL_kECDHE)) != 0));
- if (s->session->not_resumable)
- /* do not send a session ticket */
- s->ext.ticket_expected = 0;
- }
- } else {
- /* Session-id reuse */
- s->s3->tmp.new_cipher = s->session->cipher;
- }
-
- /*-
- * we now have the following setup.
- * client_random
- * cipher_list - our preferred list of ciphers
- * ciphers - the clients preferred list of ciphers
- * compression - basically ignored right now
- * ssl version is set - sslv3
- * s->session - The ssl session has been setup.
- * s->hit - session reuse flag
- * s->s3->tmp.new_cipher- the new cipher to use.
- */
-
- /*
- * Call status_request callback if needed. Has to be done after the
- * certificate callbacks etc above.
- */
- if (!tls_handle_status_request(s)) {
- /* SSLfatal() already called */
- goto err;
- }
- /*
- * Call alpn_select callback if needed. Has to be done after SNI and
- * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
- * we already did this because cipher negotiation happens earlier, and
- * we must handle ALPN before we decide whether to accept early_data.
- */
- if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- wst = WORK_MORE_C;
- }
-#ifndef OPENSSL_NO_SRP
- if (wst == WORK_MORE_C) {
- int ret;
- if ((ret = ssl_check_srp_ext_ClientHello(s)) == 0) {
- /*
- * callback indicates further work to be done
- */
- s->rwstate = SSL_X509_LOOKUP;
- return WORK_MORE_C;
- }
- if (ret < 0) {
- /* SSLfatal() already called */
- goto err;
- }
- }
-#endif
-
- return WORK_FINISHED_STOP;
- err:
- return WORK_ERROR;
-}
-
-int tls_construct_server_hello(SSL *s, WPACKET *pkt)
-{
- int compm;
- size_t sl, len;
- int version;
- unsigned char *session_id;
- int usetls13 = SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING;
-
- version = usetls13 ? TLS1_2_VERSION : s->version;
- if (!WPACKET_put_bytes_u16(pkt, version)
- /*
- * Random stuff. Filling of the server_random takes place in
- * tls_process_client_hello()
- */
- || !WPACKET_memcpy(pkt,
- s->hello_retry_request == SSL_HRR_PENDING
- ? hrrrandom : s->s3->server_random,
- SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*-
- * There are several cases for the session ID to send
- * back in the server hello:
- * - For session reuse from the session cache,
- * we send back the old session ID.
- * - If stateless session reuse (using a session ticket)
- * is successful, we send back the client's "session ID"
- * (which doesn't actually identify the session).
- * - If it is a new session, we send back the new
- * session ID.
- * - However, if we want the new session to be single-use,
- * we send back a 0-length session ID.
- * - In TLSv1.3 we echo back the session id sent to us by the client
- * regardless
- * s->hit is non-zero in either case of session reuse,
- * so the following won't overwrite an ID that we're supposed
- * to send back.
- */
- if (s->session->not_resumable ||
- (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
- && !s->hit))
- s->session->session_id_length = 0;
-
- if (usetls13) {
- sl = s->tmp_session_id_len;
- session_id = s->tmp_session_id;
- } else {
- sl = s->session->session_id_length;
- session_id = s->session->session_id;
- }
-
- if (sl > sizeof(s->session->session_id)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* set up the compression method */
-#ifdef OPENSSL_NO_COMP
- compm = 0;
-#else
- if (usetls13 || s->s3->tmp.new_compression == NULL)
- compm = 0;
- else
- compm = s->s3->tmp.new_compression->id;
-#endif
-
- if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl)
- || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
- || !WPACKET_put_bytes_u8(pkt, compm)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!tls_construct_extensions(s, pkt,
- s->hello_retry_request == SSL_HRR_PENDING
- ? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
- : (SSL_IS_TLS13(s)
- ? SSL_EXT_TLS1_3_SERVER_HELLO
- : SSL_EXT_TLS1_2_SERVER_HELLO),
- NULL, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- if (s->hello_retry_request == SSL_HRR_PENDING) {
- /* Ditch the session. We'll create a new one next time around */
- SSL_SESSION_free(s->session);
- s->session = NULL;
- s->hit = 0;
-
- /*
- * Re-initialise the Transcript Hash. We're going to prepopulate it with
- * a synthetic message_hash in place of ClientHello1.
- */
- if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
- } else if (!(s->verify_mode & SSL_VERIFY_PEER)
- && !ssl3_digest_cached_records(s, 0)) {
- /* SSLfatal() already called */;
- return 0;
- }
-
- return 1;
-}
-
-int tls_construct_server_done(SSL *s, WPACKET *pkt)
-{
- if (!s->s3->tmp.cert_request) {
- if (!ssl3_digest_cached_records(s, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
- }
- return 1;
-}
-
-int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
-{
-#ifndef OPENSSL_NO_DH
- EVP_PKEY *pkdh = NULL;
-#endif
-#ifndef OPENSSL_NO_EC
- unsigned char *encodedPoint = NULL;
- size_t encodedlen = 0;
- int curve_id = 0;
-#endif
- const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
- int i;
- unsigned long type;
- const BIGNUM *r[4];
- EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
- EVP_PKEY_CTX *pctx = NULL;
- size_t paramlen, paramoffset;
-
- if (!WPACKET_get_total_written(pkt, &paramoffset)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (md_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- type = s->s3->tmp.new_cipher->algorithm_mkey;
-
- r[0] = r[1] = r[2] = r[3] = NULL;
-#ifndef OPENSSL_NO_PSK
- /* Plain PSK or RSAPSK nothing to do */
- if (type & (SSL_kPSK | SSL_kRSAPSK)) {
- } else
-#endif /* !OPENSSL_NO_PSK */
-#ifndef OPENSSL_NO_DH
- if (type & (SSL_kDHE | SSL_kDHEPSK)) {
- CERT *cert = s->cert;
-
- EVP_PKEY *pkdhp = NULL;
- DH *dh;
-
- if (s->cert->dh_tmp_auto) {
- DH *dhp = ssl_get_auto_dh(s);
- pkdh = EVP_PKEY_new();
- if (pkdh == NULL || dhp == NULL) {
- DH_free(dhp);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- EVP_PKEY_assign_DH(pkdh, dhp);
- pkdhp = pkdh;
- } else {
- pkdhp = cert->dh_tmp;
- }
- if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) {
- DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024);
- pkdh = ssl_dh_to_pkey(dhp);
- if (pkdh == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- pkdhp = pkdh;
- }
- if (pkdhp == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_MISSING_TMP_DH_KEY);
- goto err;
- }
- if (!ssl_security(s, SSL_SECOP_TMP_DH,
- EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_DH_KEY_TOO_SMALL);
- goto err;
- }
- if (s->s3->tmp.pkey != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- s->s3->tmp.pkey = ssl_generate_pkey(pkdhp);
- if (s->s3->tmp.pkey == NULL) {
+
+ if (cipher == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_NO_SHARED_CIPHER);
+ goto err;
+ }
+ s->s3->tmp.new_cipher = cipher;
+ }
+ if (!s->hit) {
+ if (!tls_choose_sigalg(s, 1)) {
+ /* SSLfatal already called */
+ goto err;
+ }
+ /* check whether we should disable session resumption */
+ if (s->not_resumable_session_cb != NULL)
+ s->session->not_resumable =
+ s->not_resumable_session_cb(s,
+ ((s->s3->tmp.new_cipher->algorithm_mkey
+ & (SSL_kDHE | SSL_kECDHE)) != 0));
+ if (s->session->not_resumable)
+ /* do not send a session ticket */
+ s->ext.ticket_expected = 0;
+ }
+ } else {
+ /* Session-id reuse */
+ s->s3->tmp.new_cipher = s->session->cipher;
+ }
+
+ /*-
+ * we now have the following setup.
+ * client_random
+ * cipher_list - our preferred list of ciphers
+ * ciphers - the clients preferred list of ciphers
+ * compression - basically ignored right now
+ * ssl version is set - sslv3
+ * s->session - The ssl session has been setup.
+ * s->hit - session reuse flag
+ * s->s3->tmp.new_cipher- the new cipher to use.
+ */
+
+ /*
+ * Call status_request callback if needed. Has to be done after the
+ * certificate callbacks etc above.
+ */
+ if (!tls_handle_status_request(s)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ /*
+ * Call alpn_select callback if needed. Has to be done after SNI and
+ * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
+ * we already did this because cipher negotiation happens earlier, and
+ * we must handle ALPN before we decide whether to accept early_data.
+ */
+ if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ wst = WORK_MORE_C;
+ }
+#ifndef OPENSSL_NO_SRP
+ if (wst == WORK_MORE_C) {
+ int ret;
+ if ((ret = ssl_check_srp_ext_ClientHello(s)) == 0) {
+ /*
+ * callback indicates further work to be done
+ */
+ s->rwstate = SSL_X509_LOOKUP;
+ return WORK_MORE_C;
+ }
+ if (ret < 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ }
+#endif
+
+ return WORK_FINISHED_STOP;
+ err:
+ return WORK_ERROR;
+}
+
+int tls_construct_server_hello(SSL *s, WPACKET *pkt)
+{
+ int compm;
+ size_t sl, len;
+ int version;
+ unsigned char *session_id;
+ int usetls13 = SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING;
+
+ version = usetls13 ? TLS1_2_VERSION : s->version;
+ if (!WPACKET_put_bytes_u16(pkt, version)
+ /*
+ * Random stuff. Filling of the server_random takes place in
+ * tls_process_client_hello()
+ */
+ || !WPACKET_memcpy(pkt,
+ s->hello_retry_request == SSL_HRR_PENDING
+ ? hrrrandom : s->s3->server_random,
+ SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*-
+ * There are several cases for the session ID to send
+ * back in the server hello:
+ * - For session reuse from the session cache,
+ * we send back the old session ID.
+ * - If stateless session reuse (using a session ticket)
+ * is successful, we send back the client's "session ID"
+ * (which doesn't actually identify the session).
+ * - If it is a new session, we send back the new
+ * session ID.
+ * - However, if we want the new session to be single-use,
+ * we send back a 0-length session ID.
+ * - In TLSv1.3 we echo back the session id sent to us by the client
+ * regardless
+ * s->hit is non-zero in either case of session reuse,
+ * so the following won't overwrite an ID that we're supposed
+ * to send back.
+ */
+ if (s->session->not_resumable ||
+ (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
+ && !s->hit))
+ s->session->session_id_length = 0;
+
+ if (usetls13) {
+ sl = s->tmp_session_id_len;
+ session_id = s->tmp_session_id;
+ } else {
+ sl = s->session->session_id_length;
+ session_id = s->session->session_id;
+ }
+
+ if (sl > sizeof(s->session->session_id)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* set up the compression method */
+#ifdef OPENSSL_NO_COMP
+ compm = 0;
+#else
+ if (usetls13 || s->s3->tmp.new_compression == NULL)
+ compm = 0;
+ else
+ compm = s->s3->tmp.new_compression->id;
+#endif
+
+ if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl)
+ || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
+ || !WPACKET_put_bytes_u8(pkt, compm)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!tls_construct_extensions(s, pkt,
+ s->hello_retry_request == SSL_HRR_PENDING
+ ? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
+ : (SSL_IS_TLS13(s)
+ ? SSL_EXT_TLS1_3_SERVER_HELLO
+ : SSL_EXT_TLS1_2_SERVER_HELLO),
+ NULL, 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
+ /* Ditch the session. We'll create a new one next time around */
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ s->hit = 0;
+
+ /*
+ * Re-initialise the Transcript Hash. We're going to prepopulate it with
+ * a synthetic message_hash in place of ClientHello1.
+ */
+ if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ } else if (!(s->verify_mode & SSL_VERIFY_PEER)
+ && !ssl3_digest_cached_records(s, 0)) {
+ /* SSLfatal() already called */;
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_server_done(SSL *s, WPACKET *pkt)
+{
+ if (!s->s3->tmp.cert_request) {
+ if (!ssl3_digest_cached_records(s, 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
+{
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY *pkdh = NULL;
+#endif
+#ifndef OPENSSL_NO_EC
+ unsigned char *encodedPoint = NULL;
+ size_t encodedlen = 0;
+ int curve_id = 0;
+#endif
+ const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
+ int i;
+ unsigned long type;
+ const BIGNUM *r[4];
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
+ EVP_PKEY_CTX *pctx = NULL;
+ size_t paramlen, paramoffset;
+
+ if (!WPACKET_get_total_written(pkt, &paramoffset)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (md_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ type = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ r[0] = r[1] = r[2] = r[3] = NULL;
+#ifndef OPENSSL_NO_PSK
+ /* Plain PSK or RSAPSK nothing to do */
+ if (type & (SSL_kPSK | SSL_kRSAPSK)) {
+ } else
+#endif /* !OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_DH
+ if (type & (SSL_kDHE | SSL_kDHEPSK)) {
+ CERT *cert = s->cert;
+
+ EVP_PKEY *pkdhp = NULL;
+ DH *dh;
+
+ if (s->cert->dh_tmp_auto) {
+ DH *dhp = ssl_get_auto_dh(s);
+ pkdh = EVP_PKEY_new();
+ if (pkdh == NULL || dhp == NULL) {
+ DH_free(dhp);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ EVP_PKEY_assign_DH(pkdh, dhp);
+ pkdhp = pkdh;
+ } else {
+ pkdhp = cert->dh_tmp;
+ }
+ if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) {
+ DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024);
+ pkdh = ssl_dh_to_pkey(dhp);
+ if (pkdh == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ pkdhp = pkdh;
+ }
+ if (pkdhp == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_MISSING_TMP_DH_KEY);
+ goto err;
+ }
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_DH_KEY_TOO_SMALL);
+ goto err;
+ }
+ if (s->s3->tmp.pkey != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ s->s3->tmp.pkey = ssl_generate_pkey(pkdhp);
+ if (s->s3->tmp.pkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, 0, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey);
- if (dh == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- EVP_PKEY_free(pkdh);
- pkdh = NULL;
-
- DH_get0_pqg(dh, &r[0], NULL, &r[1]);
- DH_get0_key(dh, &r[2], NULL);
- } else
-#endif
-#ifndef OPENSSL_NO_EC
- if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
-
- if (s->s3->tmp.pkey != NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Get NID of appropriate shared curve */
- curve_id = tls1_shared_group(s, -2);
- if (curve_id == 0) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
- goto err;
- }
- s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id);
- /* Generate a new key for this curve */
- if (s->s3->tmp.pkey == NULL) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /* Encode the public key. */
- encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
- &encodedPoint);
- if (encodedlen == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
- goto err;
- }
-
- /*
- * We'll generate the serverKeyExchange message explicitly so we
- * can set these to NULLs
- */
- r[0] = NULL;
- r[1] = NULL;
- r[2] = NULL;
- r[3] = NULL;
- } else
-#endif /* !OPENSSL_NO_EC */
-#ifndef OPENSSL_NO_SRP
- if (type & SSL_kSRP) {
- if ((s->srp_ctx.N == NULL) ||
- (s->srp_ctx.g == NULL) ||
- (s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_MISSING_SRP_PARAM);
- goto err;
- }
- r[0] = s->srp_ctx.N;
- r[1] = s->srp_ctx.g;
- r[2] = s->srp_ctx.s;
- r[3] = s->srp_ctx.B;
- } else
-#endif
- {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
- goto err;
- }
-
- if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
- || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
- lu = NULL;
- } else if (lu == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
-#ifndef OPENSSL_NO_PSK
- if (type & SSL_PSK) {
- size_t len = (s->cert->psk_identity_hint == NULL)
- ? 0 : strlen(s->cert->psk_identity_hint);
-
- /*
- * It should not happen that len > PSK_MAX_IDENTITY_LEN - we already
- * checked this when we set the identity hint - but just in case
- */
- if (len > PSK_MAX_IDENTITY_LEN
- || !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
- len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-#endif
-
- for (i = 0; i < 4 && r[i] != NULL; i++) {
- unsigned char *binval;
- int res;
-
-#ifndef OPENSSL_NO_SRP
- if ((i == 2) && (type & SSL_kSRP)) {
- res = WPACKET_start_sub_packet_u8(pkt);
- } else
-#endif
- res = WPACKET_start_sub_packet_u16(pkt);
-
- if (!res) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
-#ifndef OPENSSL_NO_DH
- /*-
- * for interoperability with some versions of the Microsoft TLS
- * stack, we need to zero pad the DHE pub key to the same length
- * as the prime
- */
- if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK))) {
- size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]);
-
- if (len > 0) {
- if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- memset(binval, 0, len);
- }
- }
-#endif
- if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- BN_bn2bin(r[i], binval);
- }
-
-#ifndef OPENSSL_NO_EC
- if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
- /*
- * We only support named (not generic) curves. In this situation, the
- * ServerKeyExchange message has: [1 byte CurveType], [2 byte CurveName]
- * [1 byte length of encoded point], followed by the actual encoded
- * point itself
- */
- if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE)
- || !WPACKET_put_bytes_u8(pkt, 0)
- || !WPACKET_put_bytes_u8(pkt, curve_id)
- || !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- OPENSSL_free(encodedPoint);
- encodedPoint = NULL;
- }
-#endif
-
- /* not anonymous */
- if (lu != NULL) {
- EVP_PKEY *pkey = s->s3->tmp.cert->privatekey;
- const EVP_MD *md;
- unsigned char *sigbytes1, *sigbytes2, *tbs;
- size_t siglen, tbslen;
- int rv;
-
- if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /* Get length of the parameters we have written above */
- if (!WPACKET_get_length(pkt, &paramlen)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /* send signature algorithm */
- if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /*
- * Create the signature. We don't know the actual length of the sig
- * until after we've created it, so we reserve enough bytes for it
- * up front, and then properly allocate them in the WPACKET
- * afterwards.
- */
- siglen = EVP_PKEY_size(pkey);
- if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
- || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- if (lu->sig == EVP_PKEY_RSA_PSS) {
- if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
- || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_EVP_LIB);
- goto err;
- }
- }
- tbslen = construct_key_exchange_tbs(s, &tbs,
- s->init_buf->data + paramoffset,
- paramlen);
- if (tbslen == 0) {
- /* SSLfatal() already called */
- goto err;
- }
- rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen);
- OPENSSL_free(tbs);
- if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
- || sigbytes1 != sigbytes2) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- }
-
- EVP_MD_CTX_free(md_ctx);
- return 1;
- err:
-#ifndef OPENSSL_NO_DH
- EVP_PKEY_free(pkdh);
-#endif
-#ifndef OPENSSL_NO_EC
- OPENSSL_free(encodedPoint);
-#endif
- EVP_MD_CTX_free(md_ctx);
- return 0;
-}
-
-int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
-{
- if (SSL_IS_TLS13(s)) {
- /* Send random context when doing post-handshake auth */
- if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
- OPENSSL_free(s->pha_context);
- s->pha_context_len = 32;
+ goto err;
+ }
+
+ dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey);
+ if (dh == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ EVP_PKEY_free(pkdh);
+ pkdh = NULL;
+
+ DH_get0_pqg(dh, &r[0], NULL, &r[1]);
+ DH_get0_key(dh, &r[2], NULL);
+ } else
+#endif
+#ifndef OPENSSL_NO_EC
+ if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
+
+ if (s->s3->tmp.pkey != NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Get NID of appropriate shared curve */
+ curve_id = tls1_shared_group(s, -2);
+ if (curve_id == 0) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
+ goto err;
+ }
+ s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id);
+ /* Generate a new key for this curve */
+ if (s->s3->tmp.pkey == NULL) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /* Encode the public key. */
+ encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
+ &encodedPoint);
+ if (encodedlen == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /*
+ * We'll generate the serverKeyExchange message explicitly so we
+ * can set these to NULLs
+ */
+ r[0] = NULL;
+ r[1] = NULL;
+ r[2] = NULL;
+ r[3] = NULL;
+ } else
+#endif /* !OPENSSL_NO_EC */
+#ifndef OPENSSL_NO_SRP
+ if (type & SSL_kSRP) {
+ if ((s->srp_ctx.N == NULL) ||
+ (s->srp_ctx.g == NULL) ||
+ (s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_MISSING_SRP_PARAM);
+ goto err;
+ }
+ r[0] = s->srp_ctx.N;
+ r[1] = s->srp_ctx.g;
+ r[2] = s->srp_ctx.s;
+ r[3] = s->srp_ctx.B;
+ } else
+#endif
+ {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+ goto err;
+ }
+
+ if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
+ || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
+ lu = NULL;
+ } else if (lu == NULL) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_PSK
+ if (type & SSL_PSK) {
+ size_t len = (s->cert->psk_identity_hint == NULL)
+ ? 0 : strlen(s->cert->psk_identity_hint);
+
+ /*
+ * It should not happen that len > PSK_MAX_IDENTITY_LEN - we already
+ * checked this when we set the identity hint - but just in case
+ */
+ if (len > PSK_MAX_IDENTITY_LEN
+ || !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
+ len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+#endif
+
+ for (i = 0; i < 4 && r[i] != NULL; i++) {
+ unsigned char *binval;
+ int res;
+
+#ifndef OPENSSL_NO_SRP
+ if ((i == 2) && (type & SSL_kSRP)) {
+ res = WPACKET_start_sub_packet_u8(pkt);
+ } else
+#endif
+ res = WPACKET_start_sub_packet_u16(pkt);
+
+ if (!res) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_DH
+ /*-
+ * for interoperability with some versions of the Microsoft TLS
+ * stack, we need to zero pad the DHE pub key to the same length
+ * as the prime
+ */
+ if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK))) {
+ size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]);
+
+ if (len > 0) {
+ if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ memset(binval, 0, len);
+ }
+ }
+#endif
+ if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ BN_bn2bin(r[i], binval);
+ }
+
+#ifndef OPENSSL_NO_EC
+ if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ /*
+ * We only support named (not generic) curves. In this situation, the
+ * ServerKeyExchange message has: [1 byte CurveType], [2 byte CurveName]
+ * [1 byte length of encoded point], followed by the actual encoded
+ * point itself
+ */
+ if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE)
+ || !WPACKET_put_bytes_u8(pkt, 0)
+ || !WPACKET_put_bytes_u8(pkt, curve_id)
+ || !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
+ }
+#endif
+
+ /* not anonymous */
+ if (lu != NULL) {
+ EVP_PKEY *pkey = s->s3->tmp.cert->privatekey;
+ const EVP_MD *md;
+ unsigned char *sigbytes1, *sigbytes2, *tbs;
+ size_t siglen, tbslen;
+ int rv;
+
+ if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ /* Get length of the parameters we have written above */
+ if (!WPACKET_get_length(pkt, &paramlen)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ /* send signature algorithm */
+ if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ /*
+ * Create the signature. We don't know the actual length of the sig
+ * until after we've created it, so we reserve enough bytes for it
+ * up front, and then properly allocate them in the WPACKET
+ * afterwards.
+ */
+ siglen = EVP_PKEY_size(pkey);
+ if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
+ || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ if (lu->sig == EVP_PKEY_RSA_PSS) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
+ || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ }
+ tbslen = construct_key_exchange_tbs(s, &tbs,
+ s->init_buf->data + paramoffset,
+ paramlen);
+ if (tbslen == 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen);
+ OPENSSL_free(tbs);
+ if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
+ || sigbytes1 != sigbytes2) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ EVP_MD_CTX_free(md_ctx);
+ return 1;
+ err:
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY_free(pkdh);
+#endif
+#ifndef OPENSSL_NO_EC
+ OPENSSL_free(encodedPoint);
+#endif
+ EVP_MD_CTX_free(md_ctx);
+ return 0;
+}
+
+int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
+{
+ if (SSL_IS_TLS13(s)) {
+ /* Send random context when doing post-handshake auth */
+ if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
+ OPENSSL_free(s->pha_context);
+ s->pha_context_len = 32;
if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL) {
s->pha_context_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
if (RAND_bytes(s->pha_context, s->pha_context_len) <= 0
|| !WPACKET_sub_memcpy_u8(pkt, s->pha_context,
s->pha_context_len)) {
@@ -2869,534 +2869,534 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
ERR_R_INTERNAL_ERROR);
return 0;
}
- /* reset the handshake hash back to just after the ClientFinished */
- if (!tls13_restore_handshake_digest_for_pha(s)) {
- /* SSLfatal() already called */
- return 0;
- }
- } else {
- if (!WPACKET_put_bytes_u8(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- if (!tls_construct_extensions(s, pkt,
- SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, NULL,
- 0)) {
- /* SSLfatal() already called */
- return 0;
- }
- goto done;
- }
-
- /* get the list of acceptable cert types */
- if (!WPACKET_start_sub_packet_u8(pkt)
- || !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (SSL_USE_SIGALGS(s)) {
- const uint16_t *psigs;
- size_t nl = tls12_get_psigalgs(s, 1, &psigs);
-
- if (!WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
- || !tls12_copy_sigalgs(s, pkt, psigs, nl)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- if (!construct_ca_names(s, get_ca_names(s), pkt)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- done:
- s->certreqs_sent++;
- s->s3->tmp.cert_request = 1;
- return 1;
-}
-
-static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
-{
-#ifndef OPENSSL_NO_PSK
- unsigned char psk[PSK_MAX_PSK_LEN];
- size_t psklen;
- PACKET psk_identity;
-
- if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
- if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return 0;
- }
- if (s->psk_server_callback == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_PSK_NO_SERVER_CB);
- return 0;
- }
-
- if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- psklen = s->psk_server_callback(s, s->session->psk_identity,
- psk, sizeof(psk));
-
- if (psklen > PSK_MAX_PSK_LEN) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- return 0;
- } else if (psklen == 0) {
- /*
- * PSK related to the given identity not found
- */
- SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
- SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- SSL_R_PSK_IDENTITY_NOT_FOUND);
- return 0;
- }
-
- OPENSSL_free(s->s3->tmp.psk);
- s->s3->tmp.psk = OPENSSL_memdup(psk, psklen);
- OPENSSL_cleanse(psk, psklen);
-
- if (s->s3->tmp.psk == NULL) {
+ /* reset the handshake hash back to just after the ClientFinished */
+ if (!tls13_restore_handshake_digest_for_pha(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ } else {
+ if (!WPACKET_put_bytes_u8(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ if (!tls_construct_extensions(s, pkt,
+ SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, NULL,
+ 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ goto done;
+ }
+
+ /* get the list of acceptable cert types */
+ if (!WPACKET_start_sub_packet_u8(pkt)
+ || !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (SSL_USE_SIGALGS(s)) {
+ const uint16_t *psigs;
+ size_t nl = tls12_get_psigalgs(s, 1, &psigs);
+
+ if (!WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
+ || !tls12_copy_sigalgs(s, pkt, psigs, nl)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ if (!construct_ca_names(s, get_ca_names(s), pkt)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ done:
+ s->certreqs_sent++;
+ s->s3->tmp.cert_request = 1;
+ return 1;
+}
+
+static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_PSK
+ unsigned char psk[PSK_MAX_PSK_LEN];
+ size_t psklen;
+ PACKET psk_identity;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ if (s->psk_server_callback == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ SSL_R_PSK_NO_SERVER_CB);
+ return 0;
+ }
+
+ if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ psklen = s->psk_server_callback(s, s->session->psk_identity,
+ psk, sizeof(psk));
+
+ if (psklen > PSK_MAX_PSK_LEN) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ } else if (psklen == 0) {
+ /*
+ * PSK related to the given identity not found
+ */
+ SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
+ SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ return 0;
+ }
+
+ OPENSSL_free(s->s3->tmp.psk);
+ s->s3->tmp.psk = OPENSSL_memdup(psk, psklen);
+ OPENSSL_cleanse(psk, psklen);
+
+ if (s->s3->tmp.psk == NULL) {
s->s3->tmp.psklen = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- s->s3->tmp.psklen = psklen;
-
- return 1;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
-{
-#ifndef OPENSSL_NO_RSA
- unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
- int decrypt_len;
- unsigned char decrypt_good, version_good;
- size_t j, padding_len;
- PACKET enc_premaster;
- RSA *rsa = NULL;
- unsigned char *rsa_decrypt = NULL;
- int ret = 0;
-
- rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey);
- if (rsa == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- SSL_R_MISSING_RSA_CERTIFICATE);
- return 0;
- }
-
- /* SSLv3 and pre-standard DTLS omit the length bytes. */
- if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) {
- enc_premaster = *pkt;
- } else {
- if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- SSL_R_LENGTH_MISMATCH);
- return 0;
- }
- }
-
- /*
- * We want to be sure that the plaintext buffer size makes it safe to
- * iterate over the entire size of a premaster secret
- * (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because
- * their ciphertext cannot accommodate a premaster secret anyway.
- */
- if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- RSA_R_KEY_SIZE_TOO_SMALL);
- return 0;
- }
-
- rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
- if (rsa_decrypt == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- /*
- * We must not leak whether a decryption failure occurs because of
- * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
- * section 7.4.7.1). The code follows that advice of the TLS RFC and
- * generates a random premaster secret for the case that the decrypt
- * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
- */
-
- if (RAND_priv_bytes(rand_premaster_secret,
- sizeof(rand_premaster_secret)) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * Decrypt with no padding. PKCS#1 padding will be removed as part of
- * the timing-sensitive code below.
- */
- /* TODO(size_t): Convert this function */
- decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster),
- PACKET_data(&enc_premaster),
- rsa_decrypt, rsa, RSA_NO_PADDING);
- if (decrypt_len < 0) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Check the padding. See RFC 3447, section 7.2.2. */
-
- /*
- * The smallest padded premaster is 11 bytes of overhead. Small keys
- * are publicly invalid, so this may return immediately. This ensures
- * PS is at least 8 bytes.
- */
- if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
- SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- SSL_R_DECRYPTION_FAILED);
- goto err;
- }
-
- padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH;
- decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) &
- constant_time_eq_int_8(rsa_decrypt[1], 2);
- for (j = 2; j < padding_len - 1; j++) {
- decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]);
- }
- decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]);
-
- /*
- * If the version in the decrypted pre-master secret is correct then
- * version_good will be 0xff, otherwise it'll be zero. The
- * Klima-Pokorny-Rosa extension of Bleichenbacher's attack
- * (http://eprint.iacr.org/2003/052/) exploits the version number
- * check as a "bad version oracle". Thus version checks are done in
- * constant time and are treated like any other decryption error.
- */
- version_good =
- constant_time_eq_8(rsa_decrypt[padding_len],
- (unsigned)(s->client_version >> 8));
- version_good &=
- constant_time_eq_8(rsa_decrypt[padding_len + 1],
- (unsigned)(s->client_version & 0xff));
-
- /*
- * The premaster secret must contain the same version number as the
- * ClientHello to detect version rollback attacks (strangely, the
- * protocol does not offer such protection for DH ciphersuites).
- * However, buggy clients exist that send the negotiated protocol
- * version instead if the server does not support the requested
- * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such
- * clients.
- */
- if (s->options & SSL_OP_TLS_ROLLBACK_BUG) {
- unsigned char workaround_good;
- workaround_good = constant_time_eq_8(rsa_decrypt[padding_len],
- (unsigned)(s->version >> 8));
- workaround_good &=
- constant_time_eq_8(rsa_decrypt[padding_len + 1],
- (unsigned)(s->version & 0xff));
- version_good |= workaround_good;
- }
-
- /*
- * Both decryption and version must be good for decrypt_good to
- * remain non-zero (0xff).
- */
- decrypt_good &= version_good;
-
- /*
- * Now copy rand_premaster_secret over from p using
- * decrypt_good_mask. If decryption failed, then p does not
- * contain valid plaintext, however, a check above guarantees
- * it is still sufficiently large to read from.
- */
- for (j = 0; j < sizeof(rand_premaster_secret); j++) {
- rsa_decrypt[padding_len + j] =
- constant_time_select_8(decrypt_good,
- rsa_decrypt[padding_len + j],
- rand_premaster_secret[j]);
- }
-
- if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len,
- sizeof(rand_premaster_secret), 0)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- ret = 1;
- err:
- OPENSSL_free(rsa_decrypt);
- return ret;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
-{
-#ifndef OPENSSL_NO_DH
- EVP_PKEY *skey = NULL;
- DH *cdh;
- unsigned int i;
- BIGNUM *pub_key;
- const unsigned char *data;
- EVP_PKEY *ckey = NULL;
- int ret = 0;
-
- if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
- goto err;
- }
- skey = s->s3->tmp.pkey;
- if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_MISSING_TMP_DH_KEY);
- goto err;
- }
-
- if (PACKET_remaining(pkt) == 0L) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_MISSING_TMP_DH_KEY);
- goto err;
- }
- if (!PACKET_get_bytes(pkt, &data, i)) {
- /* We already checked we have enough data */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- ckey = EVP_PKEY_new();
- if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- SSL_R_BN_LIB);
- goto err;
- }
-
- cdh = EVP_PKEY_get0_DH(ckey);
- pub_key = BN_bin2bn(data, i, NULL);
- if (pub_key == NULL || cdh == NULL || !DH_set0_key(cdh, pub_key, NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- BN_free(pub_key);
- goto err;
- }
-
- if (ssl_derive(s, skey, ckey, 1) == 0) {
- /* SSLfatal() already called */
- goto err;
- }
-
- ret = 1;
- EVP_PKEY_free(s->s3->tmp.pkey);
- s->s3->tmp.pkey = NULL;
- err:
- EVP_PKEY_free(ckey);
- return ret;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
-{
-#ifndef OPENSSL_NO_EC
- EVP_PKEY *skey = s->s3->tmp.pkey;
- EVP_PKEY *ckey = NULL;
- int ret = 0;
-
- if (PACKET_remaining(pkt) == 0L) {
- /* We don't support ECDH client auth */
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE,
- SSL_R_MISSING_TMP_ECDH_KEY);
- goto err;
- } else {
- unsigned int i;
- const unsigned char *data;
-
- /*
- * Get client's public key from encoded point in the
- * ClientKeyExchange message.
- */
-
- /* Get encoded point length */
- if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- if (skey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- SSL_R_MISSING_TMP_ECDH_KEY);
- goto err;
- }
-
- ckey = EVP_PKEY_new();
- if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- ERR_R_EVP_LIB);
- goto err;
- }
- if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- ERR_R_EC_LIB);
- goto err;
- }
- }
-
- if (ssl_derive(s, skey, ckey, 1) == 0) {
- /* SSLfatal() already called */
- goto err;
- }
-
- ret = 1;
- EVP_PKEY_free(s->s3->tmp.pkey);
- s->s3->tmp.pkey = NULL;
- err:
- EVP_PKEY_free(ckey);
-
- return ret;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_cke_srp(SSL *s, PACKET *pkt)
-{
-#ifndef OPENSSL_NO_SRP
- unsigned int i;
- const unsigned char *data;
-
- if (!PACKET_get_net_2(pkt, &i)
- || !PACKET_get_bytes(pkt, &data, i)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- SSL_R_BAD_SRP_A_LENGTH);
- return 0;
- }
- if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- ERR_R_BN_LIB);
- return 0;
- }
- if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CKE_SRP,
- SSL_R_BAD_SRP_PARAMETERS);
- return 0;
- }
- OPENSSL_free(s->session->srp_username);
- s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
- if (s->session->srp_username == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- if (!srp_generate_server_master_secret(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-static int tls_process_cke_gost(SSL *s, PACKET *pkt)
-{
-#ifndef OPENSSL_NO_GOST
- EVP_PKEY_CTX *pkey_ctx;
- EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
- unsigned char premaster_secret[32];
- const unsigned char *start;
- size_t outlen = 32, inlen;
- unsigned long alg_a;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ s->s3->tmp.psklen = psklen;
+
+ return 1;
+#else
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_RSA
+ unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
+ int decrypt_len;
+ unsigned char decrypt_good, version_good;
+ size_t j, padding_len;
+ PACKET enc_premaster;
+ RSA *rsa = NULL;
+ unsigned char *rsa_decrypt = NULL;
+ int ret = 0;
+
+ rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey);
+ if (rsa == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ SSL_R_MISSING_RSA_CERTIFICATE);
+ return 0;
+ }
+
+ /* SSLv3 and pre-standard DTLS omit the length bytes. */
+ if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) {
+ enc_premaster = *pkt;
+ } else {
+ if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+ }
+
+ /*
+ * We want to be sure that the plaintext buffer size makes it safe to
+ * iterate over the entire size of a premaster secret
+ * (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because
+ * their ciphertext cannot accommodate a premaster secret anyway.
+ */
+ if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ RSA_R_KEY_SIZE_TOO_SMALL);
+ return 0;
+ }
+
+ rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
+ if (rsa_decrypt == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ /*
+ * We must not leak whether a decryption failure occurs because of
+ * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
+ * section 7.4.7.1). The code follows that advice of the TLS RFC and
+ * generates a random premaster secret for the case that the decrypt
+ * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
+ */
+
+ if (RAND_priv_bytes(rand_premaster_secret,
+ sizeof(rand_premaster_secret)) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Decrypt with no padding. PKCS#1 padding will be removed as part of
+ * the timing-sensitive code below.
+ */
+ /* TODO(size_t): Convert this function */
+ decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster),
+ PACKET_data(&enc_premaster),
+ rsa_decrypt, rsa, RSA_NO_PADDING);
+ if (decrypt_len < 0) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Check the padding. See RFC 3447, section 7.2.2. */
+
+ /*
+ * The smallest padded premaster is 11 bytes of overhead. Small keys
+ * are publicly invalid, so this may return immediately. This ensures
+ * PS is at least 8 bytes.
+ */
+ if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
+ SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ SSL_R_DECRYPTION_FAILED);
+ goto err;
+ }
+
+ padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH;
+ decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) &
+ constant_time_eq_int_8(rsa_decrypt[1], 2);
+ for (j = 2; j < padding_len - 1; j++) {
+ decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]);
+ }
+ decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]);
+
+ /*
+ * If the version in the decrypted pre-master secret is correct then
+ * version_good will be 0xff, otherwise it'll be zero. The
+ * Klima-Pokorny-Rosa extension of Bleichenbacher's attack
+ * (http://eprint.iacr.org/2003/052/) exploits the version number
+ * check as a "bad version oracle". Thus version checks are done in
+ * constant time and are treated like any other decryption error.
+ */
+ version_good =
+ constant_time_eq_8(rsa_decrypt[padding_len],
+ (unsigned)(s->client_version >> 8));
+ version_good &=
+ constant_time_eq_8(rsa_decrypt[padding_len + 1],
+ (unsigned)(s->client_version & 0xff));
+
+ /*
+ * The premaster secret must contain the same version number as the
+ * ClientHello to detect version rollback attacks (strangely, the
+ * protocol does not offer such protection for DH ciphersuites).
+ * However, buggy clients exist that send the negotiated protocol
+ * version instead if the server does not support the requested
+ * protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such
+ * clients.
+ */
+ if (s->options & SSL_OP_TLS_ROLLBACK_BUG) {
+ unsigned char workaround_good;
+ workaround_good = constant_time_eq_8(rsa_decrypt[padding_len],
+ (unsigned)(s->version >> 8));
+ workaround_good &=
+ constant_time_eq_8(rsa_decrypt[padding_len + 1],
+ (unsigned)(s->version & 0xff));
+ version_good |= workaround_good;
+ }
+
+ /*
+ * Both decryption and version must be good for decrypt_good to
+ * remain non-zero (0xff).
+ */
+ decrypt_good &= version_good;
+
+ /*
+ * Now copy rand_premaster_secret over from p using
+ * decrypt_good_mask. If decryption failed, then p does not
+ * contain valid plaintext, however, a check above guarantees
+ * it is still sufficiently large to read from.
+ */
+ for (j = 0; j < sizeof(rand_premaster_secret); j++) {
+ rsa_decrypt[padding_len + j] =
+ constant_time_select_8(decrypt_good,
+ rsa_decrypt[padding_len + j],
+ rand_premaster_secret[j]);
+ }
+
+ if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len,
+ sizeof(rand_premaster_secret), 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ ret = 1;
+ err:
+ OPENSSL_free(rsa_decrypt);
+ return ret;
+#else
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_DH
+ EVP_PKEY *skey = NULL;
+ DH *cdh;
+ unsigned int i;
+ BIGNUM *pub_key;
+ const unsigned char *data;
+ EVP_PKEY *ckey = NULL;
+ int ret = 0;
+
+ if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+ SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
+ goto err;
+ }
+ skey = s->s3->tmp.pkey;
+ if (skey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+ SSL_R_MISSING_TMP_DH_KEY);
+ goto err;
+ }
+
+ if (PACKET_remaining(pkt) == 0L) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+ SSL_R_MISSING_TMP_DH_KEY);
+ goto err;
+ }
+ if (!PACKET_get_bytes(pkt, &data, i)) {
+ /* We already checked we have enough data */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ ckey = EVP_PKEY_new();
+ if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+ SSL_R_BN_LIB);
+ goto err;
+ }
+
+ cdh = EVP_PKEY_get0_DH(ckey);
+ pub_key = BN_bin2bn(data, i, NULL);
+ if (pub_key == NULL || cdh == NULL || !DH_set0_key(cdh, pub_key, NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ BN_free(pub_key);
+ goto err;
+ }
+
+ if (ssl_derive(s, skey, ckey, 1) == 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ ret = 1;
+ EVP_PKEY_free(s->s3->tmp.pkey);
+ s->s3->tmp.pkey = NULL;
+ err:
+ EVP_PKEY_free(ckey);
+ return ret;
+#else
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_EC
+ EVP_PKEY *skey = s->s3->tmp.pkey;
+ EVP_PKEY *ckey = NULL;
+ int ret = 0;
+
+ if (PACKET_remaining(pkt) == 0L) {
+ /* We don't support ECDH client auth */
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE,
+ SSL_R_MISSING_TMP_ECDH_KEY);
+ goto err;
+ } else {
+ unsigned int i;
+ const unsigned char *data;
+
+ /*
+ * Get client's public key from encoded point in the
+ * ClientKeyExchange message.
+ */
+
+ /* Get encoded point length */
+ if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ if (skey == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+ SSL_R_MISSING_TMP_ECDH_KEY);
+ goto err;
+ }
+
+ ckey = EVP_PKEY_new();
+ if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+ ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+ ERR_R_EC_LIB);
+ goto err;
+ }
+ }
+
+ if (ssl_derive(s, skey, ckey, 1) == 0) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ ret = 1;
+ EVP_PKEY_free(s->s3->tmp.pkey);
+ s->s3->tmp.pkey = NULL;
+ err:
+ EVP_PKEY_free(ckey);
+
+ return ret;
+#else
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_srp(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_SRP
+ unsigned int i;
+ const unsigned char *data;
+
+ if (!PACKET_get_net_2(pkt, &i)
+ || !PACKET_get_bytes(pkt, &data, i)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+ SSL_R_BAD_SRP_A_LENGTH);
+ return 0;
+ }
+ if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+ ERR_R_BN_LIB);
+ return 0;
+ }
+ if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CKE_SRP,
+ SSL_R_BAD_SRP_PARAMETERS);
+ return 0;
+ }
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (!srp_generate_server_master_secret(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+#else
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+static int tls_process_cke_gost(SSL *s, PACKET *pkt)
+{
+#ifndef OPENSSL_NO_GOST
+ EVP_PKEY_CTX *pkey_ctx;
+ EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
+ unsigned char premaster_secret[32];
+ const unsigned char *start;
+ size_t outlen = 32, inlen;
+ unsigned long alg_a;
GOST_KX_MESSAGE *pKX = NULL;
const unsigned char *ptr;
- int ret = 0;
-
- /* Get our certificate private key */
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
- if (alg_a & SSL_aGOST12) {
- /*
- * New GOST ciphersuites have SSL_aGOST01 bit too
- */
- pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey;
- if (pk == NULL) {
- pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
- }
- if (pk == NULL) {
- pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
- }
- } else if (alg_a & SSL_aGOST01) {
- pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
- }
-
- pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
- if (pkey_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- /*
- * If client certificate is present and is of the same type, maybe
- * use it for key exchange. Don't mind errors from
- * EVP_PKEY_derive_set_peer, because it is completely valid to use a
- * client certificate for authorization only.
- */
- client_pub_pkey = X509_get0_pubkey(s->session->peer);
- if (client_pub_pkey) {
- if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
- ERR_clear_error();
- }
+ int ret = 0;
+
+ /* Get our certificate private key */
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ if (alg_a & SSL_aGOST12) {
+ /*
+ * New GOST ciphersuites have SSL_aGOST01 bit too
+ */
+ pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey;
+ if (pk == NULL) {
+ pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
+ }
+ if (pk == NULL) {
+ pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
+ }
+ } else if (alg_a & SSL_aGOST01) {
+ pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
+ }
+
+ pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
+ if (pkey_ctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ /*
+ * If client certificate is present and is of the same type, maybe
+ * use it for key exchange. Don't mind errors from
+ * EVP_PKEY_derive_set_peer, because it is completely valid to use a
+ * client certificate for authorization only.
+ */
+ client_pub_pkey = X509_get0_pubkey(s->session->peer);
+ if (client_pub_pkey) {
+ if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
+ ERR_clear_error();
+ }
ptr = PACKET_data(pkt);
/* Some implementations provide extra data in the opaqueBlob
@@ -3412,888 +3412,888 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt)
if (!PACKET_forward(pkt, ptr - PACKET_data(pkt))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- SSL_R_DECRYPTION_FAILED);
- goto err;
- }
-
+ SSL_R_DECRYPTION_FAILED);
+ goto err;
+ }
+
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- SSL_R_DECRYPTION_FAILED);
- goto err;
- }
-
+ SSL_R_DECRYPTION_FAILED);
+ goto err;
+ }
+
inlen = pKX->kxBlob->value.sequence->length;
start = pKX->kxBlob->value.sequence->data;
- if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
- inlen) <= 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- SSL_R_DECRYPTION_FAILED);
- goto err;
- }
- /* Generate master secret */
- if (!ssl_generate_master_secret(s, premaster_secret,
- sizeof(premaster_secret), 0)) {
- /* SSLfatal() already called */
- goto err;
- }
- /* Check if pubkey from client certificate was used */
- if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
- NULL) > 0)
- s->statem.no_cert_verify = 1;
-
- ret = 1;
- err:
- EVP_PKEY_CTX_free(pkey_ctx);
+ if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
+ inlen) <= 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+ SSL_R_DECRYPTION_FAILED);
+ goto err;
+ }
+ /* Generate master secret */
+ if (!ssl_generate_master_secret(s, premaster_secret,
+ sizeof(premaster_secret), 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ /* Check if pubkey from client certificate was used */
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
+ NULL) > 0)
+ s->statem.no_cert_verify = 1;
+
+ ret = 1;
+ err:
+ EVP_PKEY_CTX_free(pkey_ctx);
GOST_KX_MESSAGE_free(pKX);
- return ret;
-#else
- /* Should never happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
- return 0;
-#endif
-}
-
-MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
-{
- unsigned long alg_k;
-
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-
- /* For PSK parse and retrieve identity, obtain PSK key */
- if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- if (alg_k & SSL_kPSK) {
- /* Identity extracted earlier: should be nothing left */
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- /* PSK handled by ssl_generate_master_secret */
- if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
- if (!tls_process_cke_rsa(s, pkt)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
- if (!tls_process_cke_dhe(s, pkt)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
- if (!tls_process_cke_ecdhe(s, pkt)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k & SSL_kSRP) {
- if (!tls_process_cke_srp(s, pkt)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (alg_k & SSL_kGOST) {
- if (!tls_process_cke_gost(s, pkt)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
- SSL_R_UNKNOWN_CIPHER_TYPE);
- goto err;
- }
-
- return MSG_PROCESS_CONTINUE_PROCESSING;
- err:
-#ifndef OPENSSL_NO_PSK
- OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
- s->s3->tmp.psk = NULL;
+ return ret;
+#else
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+#endif
+}
+
+MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
+{
+ unsigned long alg_k;
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+ /* For PSK parse and retrieve identity, obtain PSK key */
+ if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ if (alg_k & SSL_kPSK) {
+ /* Identity extracted earlier: should be nothing left */
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ /* PSK handled by ssl_generate_master_secret */
+ if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
+ if (!tls_process_cke_rsa(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (!tls_process_cke_dhe(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
+ if (!tls_process_cke_ecdhe(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_process_cke_srp(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (alg_k & SSL_kGOST) {
+ if (!tls_process_cke_gost(s, pkt)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+ SSL_R_UNKNOWN_CIPHER_TYPE);
+ goto err;
+ }
+
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+ err:
+#ifndef OPENSSL_NO_PSK
+ OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
+ s->s3->tmp.psk = NULL;
s->s3->tmp.psklen = 0;
-#endif
- return MSG_PROCESS_ERROR;
-}
-
-WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
-{
-#ifndef OPENSSL_NO_SCTP
- if (wst == WORK_MORE_A) {
- if (SSL_IS_DTLS(s)) {
- unsigned char sctpauthkey[64];
- char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
- size_t labellen;
- /*
- * Add new shared key for SCTP-Auth, will be ignored if no SCTP
- * used.
- */
- memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
- sizeof(DTLS1_SCTP_AUTH_LABEL));
-
- /* Don't include the terminating zero. */
- labellen = sizeof(labelbuffer) - 1;
- if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
- labellen += 1;
-
- if (SSL_export_keying_material(s, sctpauthkey,
- sizeof(sctpauthkey), labelbuffer,
- labellen, NULL, 0,
- 0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
- }
-
- BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
- sizeof(sctpauthkey), sctpauthkey);
- }
- }
-#endif
-
- if (s->statem.no_cert_verify || !s->session->peer) {
- /*
- * No certificate verify or no peer certificate so we no longer need
- * the handshake_buffer
- */
- if (!ssl3_digest_cached_records(s, 0)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- return WORK_FINISHED_CONTINUE;
- } else {
- if (!s->s3->handshake_buffer) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- return WORK_ERROR;
- }
- /*
- * For sigalgs freeze the handshake buffer. If we support
- * extms we've done this already so this is a no-op
- */
- if (!ssl3_digest_cached_records(s, 1)) {
- /* SSLfatal() already called */
- return WORK_ERROR;
- }
- }
-
- return WORK_FINISHED_CONTINUE;
-}
-
-MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
-{
- int i;
- MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
- X509 *x = NULL;
- unsigned long l;
- const unsigned char *certstart, *certbytes;
- STACK_OF(X509) *sk = NULL;
- PACKET spkt, context;
- size_t chainidx;
- SSL_SESSION *new_sess = NULL;
-
- /*
- * To get this far we must have read encrypted data from the client. We no
- * longer tolerate unencrypted alerts. This value is ignored if less than
- * TLSv1.3
- */
- s->statem.enc_read_state = ENC_READ_STATE_VALID;
-
- if ((sk = sk_X509_new_null()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (SSL_IS_TLS13(s) && (!PACKET_get_length_prefixed_1(pkt, &context)
- || (s->pha_context == NULL && PACKET_remaining(&context) != 0)
- || (s->pha_context != NULL &&
- !PACKET_equal(&context, s->pha_context, s->pha_context_len)))) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_INVALID_CONTEXT);
- goto err;
- }
-
- if (!PACKET_get_length_prefixed_3(pkt, &spkt)
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) {
- if (!PACKET_get_net_3(&spkt, &l)
- || !PACKET_get_bytes(&spkt, &certbytes, l)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
- goto err;
- }
-
- certstart = certbytes;
- x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
- if (x == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
- goto err;
- }
- if (certbytes != (certstart + l)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_CERT_LENGTH_MISMATCH);
- goto err;
- }
-
- if (SSL_IS_TLS13(s)) {
- RAW_EXTENSION *rawexts = NULL;
- PACKET extensions;
-
- if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_BAD_LENGTH);
- goto err;
- }
- if (!tls_collect_extensions(s, &extensions,
- SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
- NULL, chainidx == 0)
- || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
- rawexts, x, chainidx,
- PACKET_remaining(&spkt) == 0)) {
- OPENSSL_free(rawexts);
- goto err;
- }
- OPENSSL_free(rawexts);
- }
-
- if (!sk_X509_push(sk, x)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- x = NULL;
- }
-
- if (sk_X509_num(sk) <= 0) {
- /* TLS does not mind 0 certs returned */
- if (s->version == SSL3_VERSION) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_NO_CERTIFICATES_RETURNED);
- goto err;
- }
- /* Fail for TLS only if we required a certificate */
- else if ((s->verify_mode & SSL_VERIFY_PEER) &&
- (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
- SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
- goto err;
- }
- /* No client certificate so digest cached records */
- if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else {
- EVP_PKEY *pkey;
- i = ssl_verify_cert_chain(s, sk);
- if (i <= 0) {
- SSLfatal(s, ssl_x509err2alert(s->verify_result),
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_CERTIFICATE_VERIFY_FAILED);
- goto err;
- }
- if (i > 1) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
- goto err;
- }
- pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
- if (pkey == NULL) {
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- goto err;
- }
- }
-
- /*
- * Sessions must be immutable once they go into the session cache. Otherwise
- * we can get multi-thread problems. Therefore we don't "update" sessions,
- * we replace them with a duplicate. Here, we need to do this every time
- * a new certificate is received via post-handshake authentication, as the
- * session may have already gone into the session cache.
- */
-
- if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
- if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- SSL_SESSION_free(s->session);
- s->session = new_sess;
- }
-
- X509_free(s->session->peer);
- s->session->peer = sk_X509_shift(sk);
- s->session->verify_result = s->verify_result;
-
- sk_X509_pop_free(s->session->peer_chain, X509_free);
- s->session->peer_chain = sk;
+#endif
+ return MSG_PROCESS_ERROR;
+}
+
+WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
+{
+#ifndef OPENSSL_NO_SCTP
+ if (wst == WORK_MORE_A) {
+ if (SSL_IS_DTLS(s)) {
+ unsigned char sctpauthkey[64];
+ char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+ size_t labellen;
+ /*
+ * Add new shared key for SCTP-Auth, will be ignored if no SCTP
+ * used.
+ */
+ memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
+ sizeof(DTLS1_SCTP_AUTH_LABEL));
+
+ /* Don't include the terminating zero. */
+ labellen = sizeof(labelbuffer) - 1;
+ if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+ labellen += 1;
+
+ if (SSL_export_keying_material(s, sctpauthkey,
+ sizeof(sctpauthkey), labelbuffer,
+ labellen, NULL, 0,
+ 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+ }
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+ }
+ }
+#endif
+
+ if (s->statem.no_cert_verify || !s->session->peer) {
+ /*
+ * No certificate verify or no peer certificate so we no longer need
+ * the handshake_buffer
+ */
+ if (!ssl3_digest_cached_records(s, 0)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ return WORK_FINISHED_CONTINUE;
+ } else {
+ if (!s->s3->handshake_buffer) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ return WORK_ERROR;
+ }
+ /*
+ * For sigalgs freeze the handshake buffer. If we support
+ * extms we've done this already so this is a no-op
+ */
+ if (!ssl3_digest_cached_records(s, 1)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
+MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
+{
+ int i;
+ MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
+ X509 *x = NULL;
+ unsigned long l;
+ const unsigned char *certstart, *certbytes;
+ STACK_OF(X509) *sk = NULL;
+ PACKET spkt, context;
+ size_t chainidx;
+ SSL_SESSION *new_sess = NULL;
+
+ /*
+ * To get this far we must have read encrypted data from the client. We no
+ * longer tolerate unencrypted alerts. This value is ignored if less than
+ * TLSv1.3
+ */
+ s->statem.enc_read_state = ENC_READ_STATE_VALID;
+
+ if ((sk = sk_X509_new_null()) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (SSL_IS_TLS13(s) && (!PACKET_get_length_prefixed_1(pkt, &context)
+ || (s->pha_context == NULL && PACKET_remaining(&context) != 0)
+ || (s->pha_context != NULL &&
+ !PACKET_equal(&context, s->pha_context, s->pha_context_len)))) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_INVALID_CONTEXT);
+ goto err;
+ }
+
+ if (!PACKET_get_length_prefixed_3(pkt, &spkt)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) {
+ if (!PACKET_get_net_3(&spkt, &l)
+ || !PACKET_get_bytes(&spkt, &certbytes, l)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ certstart = certbytes;
+ x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
+ if (x == NULL) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ if (certbytes != (certstart + l)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto err;
+ }
+
+ if (SSL_IS_TLS13(s)) {
+ RAW_EXTENSION *rawexts = NULL;
+ PACKET extensions;
+
+ if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_BAD_LENGTH);
+ goto err;
+ }
+ if (!tls_collect_extensions(s, &extensions,
+ SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
+ NULL, chainidx == 0)
+ || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
+ rawexts, x, chainidx,
+ PACKET_remaining(&spkt) == 0)) {
+ OPENSSL_free(rawexts);
+ goto err;
+ }
+ OPENSSL_free(rawexts);
+ }
+
+ if (!sk_X509_push(sk, x)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
+
+ if (sk_X509_num(sk) <= 0) {
+ /* TLS does not mind 0 certs returned */
+ if (s->version == SSL3_VERSION) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_NO_CERTIFICATES_RETURNED);
+ goto err;
+ }
+ /* Fail for TLS only if we required a certificate */
+ else if ((s->verify_mode & SSL_VERIFY_PEER) &&
+ (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
+ SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+ goto err;
+ }
+ /* No client certificate so digest cached records */
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else {
+ EVP_PKEY *pkey;
+ i = ssl_verify_cert_chain(s, sk);
+ if (i <= 0) {
+ SSLfatal(s, ssl_x509err2alert(s->verify_result),
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto err;
+ }
+ if (i > 1) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
+ goto err;
+ }
+ pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
+ if (pkey == NULL) {
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto err;
+ }
+ }
+
+ /*
+ * Sessions must be immutable once they go into the session cache. Otherwise
+ * we can get multi-thread problems. Therefore we don't "update" sessions,
+ * we replace them with a duplicate. Here, we need to do this every time
+ * a new certificate is received via post-handshake authentication, as the
+ * session may have already gone into the session cache.
+ */
+
+ if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
+ if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ SSL_SESSION_free(s->session);
+ s->session = new_sess;
+ }
+
+ X509_free(s->session->peer);
+ s->session->peer = sk_X509_shift(sk);
+ s->session->verify_result = s->verify_result;
+
+ sk_X509_pop_free(s->session->peer_chain, X509_free);
+ s->session->peer_chain = sk;
sk = NULL;
-
- /*
- * Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
- * message
- */
- if (SSL_IS_TLS13(s) && !ssl3_digest_cached_records(s, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /*
- * Inconsistency alert: cert_chain does *not* include the peer's own
- * certificate, while we do include it in statem_clnt.c
- */
-
- /* Save the current hash state for when we receive the CertificateVerify */
- if (SSL_IS_TLS13(s)) {
- if (!ssl_handshake_hash(s, s->cert_verify_hash,
- sizeof(s->cert_verify_hash),
- &s->cert_verify_hash_len)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- /* Resend session tickets */
- s->sent_tickets = 0;
- }
-
- ret = MSG_PROCESS_CONTINUE_READING;
-
- err:
- X509_free(x);
- sk_X509_pop_free(sk, X509_free);
- return ret;
-}
-
-int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
-{
- CERT_PKEY *cpk = s->s3->tmp.cert;
-
- if (cpk == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * In TLSv1.3 the certificate chain is always preceded by a 0 length context
- * for the server Certificate message
- */
- if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!ssl3_output_cert_chain(s, pkt, cpk)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add,
- unsigned char *tick_nonce)
-{
- /*
- * Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this
- * unspecified for resumed session (for simplicity).
- * In TLSv1.3 we reset the "time" field above, and always specify the
- * timeout.
- */
- if (!WPACKET_put_bytes_u32(pkt,
- (s->hit && !SSL_IS_TLS13(s))
- ? 0 : s->session->timeout)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (SSL_IS_TLS13(s)) {
- if (!WPACKET_put_bytes_u32(pkt, age_add)
- || !WPACKET_sub_memcpy_u8(pkt, tick_nonce, TICKET_NONCE_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- /* Start the sub-packet for the actual ticket data */
- if (!WPACKET_start_sub_packet_u16(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
- unsigned char *tick_nonce)
-{
- unsigned char *senc = NULL;
- EVP_CIPHER_CTX *ctx = NULL;
- HMAC_CTX *hctx = NULL;
- unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
- const unsigned char *const_p;
- int len, slen_full, slen, lenfinal;
- SSL_SESSION *sess;
- unsigned int hlen;
- SSL_CTX *tctx = s->session_ctx;
- unsigned char iv[EVP_MAX_IV_LENGTH];
- unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
- int iv_len, ok = 0;
- size_t macoffset, macendoffset;
-
- /* get session encoding length */
- slen_full = i2d_SSL_SESSION(s->session, NULL);
- /*
- * Some length values are 16 bits, so forget it if session is too
- * long
- */
- if (slen_full == 0 || slen_full > 0xFF00) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- senc = OPENSSL_malloc(slen_full);
- if (senc == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- ctx = EVP_CIPHER_CTX_new();
- hctx = HMAC_CTX_new();
- if (ctx == NULL || hctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- p = senc;
- if (!i2d_SSL_SESSION(s->session, &p)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /*
- * create a fresh copy (not shared with other threads) to clean up
- */
- const_p = senc;
- sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
- if (sess == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- slen = i2d_SSL_SESSION(sess, NULL);
- if (slen == 0 || slen > slen_full) {
- /* shouldn't ever happen */
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- SSL_SESSION_free(sess);
- goto err;
- }
- p = senc;
- if (!i2d_SSL_SESSION(sess, &p)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- SSL_SESSION_free(sess);
- goto err;
- }
- SSL_SESSION_free(sess);
-
- /*
- * Initialize HMAC and cipher contexts. If callback present it does
- * all the work otherwise use generated values from parent ctx.
- */
- if (tctx->ext.ticket_key_cb) {
- /* if 0 is returned, write an empty ticket */
- int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
- hctx, 1);
-
- if (ret == 0) {
-
- /* Put timeout and length */
- if (!WPACKET_put_bytes_u32(pkt, 0)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- OPENSSL_free(senc);
- EVP_CIPHER_CTX_free(ctx);
- HMAC_CTX_free(hctx);
- return 1;
- }
- if (ret < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- SSL_R_CALLBACK_FAILED);
- goto err;
- }
- iv_len = EVP_CIPHER_CTX_iv_length(ctx);
- } else {
- const EVP_CIPHER *cipher = EVP_aes_256_cbc();
-
- iv_len = EVP_CIPHER_iv_length(cipher);
- if (RAND_bytes(iv, iv_len) <= 0
- || !EVP_EncryptInit_ex(ctx, cipher, NULL,
- tctx->ext.secure->tick_aes_key, iv)
- || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
- sizeof(tctx->ext.secure->tick_hmac_key),
- EVP_sha256(), NULL)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- memcpy(key_name, tctx->ext.tick_key_name,
- sizeof(tctx->ext.tick_key_name));
- }
-
- if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- if (!WPACKET_get_total_written(pkt, &macoffset)
- /* Output key name */
- || !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
- /* output IV */
- || !WPACKET_memcpy(pkt, iv, iv_len)
- || !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
- &encdata1)
- /* Encrypt session data */
- || !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
- || !WPACKET_allocate_bytes(pkt, len, &encdata2)
- || encdata1 != encdata2
- || !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
- || !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
- || encdata1 + len != encdata2
- || len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
- || !WPACKET_get_total_written(pkt, &macendoffset)
- || !HMAC_Update(hctx,
- (unsigned char *)s->init_buf->data + macoffset,
- macendoffset - macoffset)
- || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
- || !HMAC_Final(hctx, macdata1, &hlen)
- || hlen > EVP_MAX_MD_SIZE
- || !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
- || macdata1 != macdata2) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* Close the sub-packet created by create_ticket_prequel() */
- if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- ok = 1;
- err:
- OPENSSL_free(senc);
- EVP_CIPHER_CTX_free(ctx);
- HMAC_CTX_free(hctx);
- return ok;
-}
-
-static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
- unsigned char *tick_nonce)
-{
- if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- if (!WPACKET_memcpy(pkt, s->session->session_id,
- s->session->session_id_length)
- || !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATEFUL_TICKET,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
-{
- SSL_CTX *tctx = s->session_ctx;
- unsigned char tick_nonce[TICKET_NONCE_SIZE];
- union {
- unsigned char age_add_c[sizeof(uint32_t)];
- uint32_t age_add;
- } age_add_u;
-
- age_add_u.age_add = 0;
-
- if (SSL_IS_TLS13(s)) {
- size_t i, hashlen;
- uint64_t nonce;
- static const unsigned char nonce_label[] = "resumption";
- const EVP_MD *md = ssl_handshake_md(s);
- int hashleni = EVP_MD_size(md);
-
- /* Ensure cast to size_t is safe */
- if (!ossl_assert(hashleni >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- hashlen = (size_t)hashleni;
-
- /*
- * If we already sent one NewSessionTicket, or we resumed then
- * s->session may already be in a cache and so we must not modify it.
- * Instead we need to take a copy of it and modify that.
- */
- if (s->sent_tickets != 0 || s->hit) {
- SSL_SESSION *new_sess = ssl_session_dup(s->session, 0);
-
- if (new_sess == NULL) {
- /* SSLfatal already called */
- goto err;
- }
-
- SSL_SESSION_free(s->session);
- s->session = new_sess;
- }
-
- if (!ssl_generate_session_id(s, s->session)) {
- /* SSLfatal() already called */
- goto err;
- }
- if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- s->session->ext.tick_age_add = age_add_u.age_add;
-
- nonce = s->next_ticket_nonce;
- for (i = TICKET_NONCE_SIZE; i > 0; i--) {
- tick_nonce[i - 1] = (unsigned char)(nonce & 0xff);
- nonce >>= 8;
- }
-
- if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
- nonce_label,
- sizeof(nonce_label) - 1,
- tick_nonce,
- TICKET_NONCE_SIZE,
- s->session->master_key,
- hashlen, 1)) {
- /* SSLfatal() already called */
- goto err;
- }
- s->session->master_key_length = hashlen;
-
- s->session->time = (long)time(NULL);
- if (s->s3->alpn_selected != NULL) {
- OPENSSL_free(s->session->ext.alpn_selected);
- s->session->ext.alpn_selected =
- OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
- if (s->session->ext.alpn_selected == NULL) {
+
+ /*
+ * Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
+ * message
+ */
+ if (SSL_IS_TLS13(s) && !ssl3_digest_cached_records(s, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /*
+ * Inconsistency alert: cert_chain does *not* include the peer's own
+ * certificate, while we do include it in statem_clnt.c
+ */
+
+ /* Save the current hash state for when we receive the CertificateVerify */
+ if (SSL_IS_TLS13(s)) {
+ if (!ssl_handshake_hash(s, s->cert_verify_hash,
+ sizeof(s->cert_verify_hash),
+ &s->cert_verify_hash_len)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /* Resend session tickets */
+ s->sent_tickets = 0;
+ }
+
+ ret = MSG_PROCESS_CONTINUE_READING;
+
+ err:
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
+{
+ CERT_PKEY *cpk = s->s3->tmp.cert;
+
+ if (cpk == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*
+ * In TLSv1.3 the certificate chain is always preceded by a 0 length context
+ * for the server Certificate message
+ */
+ if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!ssl3_output_cert_chain(s, pkt, cpk)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add,
+ unsigned char *tick_nonce)
+{
+ /*
+ * Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this
+ * unspecified for resumed session (for simplicity).
+ * In TLSv1.3 we reset the "time" field above, and always specify the
+ * timeout.
+ */
+ if (!WPACKET_put_bytes_u32(pkt,
+ (s->hit && !SSL_IS_TLS13(s))
+ ? 0 : s->session->timeout)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (SSL_IS_TLS13(s)) {
+ if (!WPACKET_put_bytes_u32(pkt, age_add)
+ || !WPACKET_sub_memcpy_u8(pkt, tick_nonce, TICKET_NONCE_SIZE)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
+ /* Start the sub-packet for the actual ticket data */
+ if (!WPACKET_start_sub_packet_u16(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
+ unsigned char *tick_nonce)
+{
+ unsigned char *senc = NULL;
+ EVP_CIPHER_CTX *ctx = NULL;
+ HMAC_CTX *hctx = NULL;
+ unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
+ const unsigned char *const_p;
+ int len, slen_full, slen, lenfinal;
+ SSL_SESSION *sess;
+ unsigned int hlen;
+ SSL_CTX *tctx = s->session_ctx;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
+ int iv_len, ok = 0;
+ size_t macoffset, macendoffset;
+
+ /* get session encoding length */
+ slen_full = i2d_SSL_SESSION(s->session, NULL);
+ /*
+ * Some length values are 16 bits, so forget it if session is too
+ * long
+ */
+ if (slen_full == 0 || slen_full > 0xFF00) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ senc = OPENSSL_malloc(slen_full);
+ if (senc == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ctx = EVP_CIPHER_CTX_new();
+ hctx = HMAC_CTX_new();
+ if (ctx == NULL || hctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ p = senc;
+ if (!i2d_SSL_SESSION(s->session, &p)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * create a fresh copy (not shared with other threads) to clean up
+ */
+ const_p = senc;
+ sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
+ if (sess == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ slen = i2d_SSL_SESSION(sess, NULL);
+ if (slen == 0 || slen > slen_full) {
+ /* shouldn't ever happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ SSL_SESSION_free(sess);
+ goto err;
+ }
+ p = senc;
+ if (!i2d_SSL_SESSION(sess, &p)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ SSL_SESSION_free(sess);
+ goto err;
+ }
+ SSL_SESSION_free(sess);
+
+ /*
+ * Initialize HMAC and cipher contexts. If callback present it does
+ * all the work otherwise use generated values from parent ctx.
+ */
+ if (tctx->ext.ticket_key_cb) {
+ /* if 0 is returned, write an empty ticket */
+ int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
+ hctx, 1);
+
+ if (ret == 0) {
+
+ /* Put timeout and length */
+ if (!WPACKET_put_bytes_u32(pkt, 0)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ OPENSSL_free(senc);
+ EVP_CIPHER_CTX_free(ctx);
+ HMAC_CTX_free(hctx);
+ return 1;
+ }
+ if (ret < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ SSL_R_CALLBACK_FAILED);
+ goto err;
+ }
+ iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+ } else {
+ const EVP_CIPHER *cipher = EVP_aes_256_cbc();
+
+ iv_len = EVP_CIPHER_iv_length(cipher);
+ if (RAND_bytes(iv, iv_len) <= 0
+ || !EVP_EncryptInit_ex(ctx, cipher, NULL,
+ tctx->ext.secure->tick_aes_key, iv)
+ || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
+ sizeof(tctx->ext.secure->tick_hmac_key),
+ EVP_sha256(), NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ memcpy(key_name, tctx->ext.tick_key_name,
+ sizeof(tctx->ext.tick_key_name));
+ }
+
+ if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ if (!WPACKET_get_total_written(pkt, &macoffset)
+ /* Output key name */
+ || !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
+ /* output IV */
+ || !WPACKET_memcpy(pkt, iv, iv_len)
+ || !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
+ &encdata1)
+ /* Encrypt session data */
+ || !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
+ || !WPACKET_allocate_bytes(pkt, len, &encdata2)
+ || encdata1 != encdata2
+ || !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
+ || !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
+ || encdata1 + len != encdata2
+ || len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
+ || !WPACKET_get_total_written(pkt, &macendoffset)
+ || !HMAC_Update(hctx,
+ (unsigned char *)s->init_buf->data + macoffset,
+ macendoffset - macoffset)
+ || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
+ || !HMAC_Final(hctx, macdata1, &hlen)
+ || hlen > EVP_MAX_MD_SIZE
+ || !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
+ || macdata1 != macdata2) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Close the sub-packet created by create_ticket_prequel() */
+ if (!WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ok = 1;
+ err:
+ OPENSSL_free(senc);
+ EVP_CIPHER_CTX_free(ctx);
+ HMAC_CTX_free(hctx);
+ return ok;
+}
+
+static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
+ unsigned char *tick_nonce)
+{
+ if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ if (!WPACKET_memcpy(pkt, s->session->session_id,
+ s->session->session_id_length)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATEFUL_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
+{
+ SSL_CTX *tctx = s->session_ctx;
+ unsigned char tick_nonce[TICKET_NONCE_SIZE];
+ union {
+ unsigned char age_add_c[sizeof(uint32_t)];
+ uint32_t age_add;
+ } age_add_u;
+
+ age_add_u.age_add = 0;
+
+ if (SSL_IS_TLS13(s)) {
+ size_t i, hashlen;
+ uint64_t nonce;
+ static const unsigned char nonce_label[] = "resumption";
+ const EVP_MD *md = ssl_handshake_md(s);
+ int hashleni = EVP_MD_size(md);
+
+ /* Ensure cast to size_t is safe */
+ if (!ossl_assert(hashleni >= 0)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hashlen = (size_t)hashleni;
+
+ /*
+ * If we already sent one NewSessionTicket, or we resumed then
+ * s->session may already be in a cache and so we must not modify it.
+ * Instead we need to take a copy of it and modify that.
+ */
+ if (s->sent_tickets != 0 || s->hit) {
+ SSL_SESSION *new_sess = ssl_session_dup(s->session, 0);
+
+ if (new_sess == NULL) {
+ /* SSLfatal already called */
+ goto err;
+ }
+
+ SSL_SESSION_free(s->session);
+ s->session = new_sess;
+ }
+
+ if (!ssl_generate_session_id(s, s->session)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ s->session->ext.tick_age_add = age_add_u.age_add;
+
+ nonce = s->next_ticket_nonce;
+ for (i = TICKET_NONCE_SIZE; i > 0; i--) {
+ tick_nonce[i - 1] = (unsigned char)(nonce & 0xff);
+ nonce >>= 8;
+ }
+
+ if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
+ nonce_label,
+ sizeof(nonce_label) - 1,
+ tick_nonce,
+ TICKET_NONCE_SIZE,
+ s->session->master_key,
+ hashlen, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ s->session->master_key_length = hashlen;
+
+ s->session->time = (long)time(NULL);
+ if (s->s3->alpn_selected != NULL) {
+ OPENSSL_free(s->session->ext.alpn_selected);
+ s->session->ext.alpn_selected =
+ OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
+ if (s->session->ext.alpn_selected == NULL) {
s->session->ext.alpn_selected_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
- }
- s->session->ext.max_early_data = s->max_early_data;
- }
-
- if (tctx->generate_ticket_cb != NULL &&
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
+ }
+ s->session->ext.max_early_data = s->max_early_data;
+ }
+
+ if (tctx->generate_ticket_cb != NULL &&
tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /*
- * If we are using anti-replay protection then we behave as if
- * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
- * is no point in using full stateless tickets.
- */
- if (SSL_IS_TLS13(s)
- && ((s->options & SSL_OP_NO_TICKET) != 0
- || (s->max_early_data > 0
- && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))) {
- if (!construct_stateful_ticket(s, pkt, age_add_u.age_add, tick_nonce)) {
- /* SSLfatal() already called */
- goto err;
- }
- } else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add,
- tick_nonce)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- if (SSL_IS_TLS13(s)) {
- if (!tls_construct_extensions(s, pkt,
- SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
- NULL, 0)) {
- /* SSLfatal() already called */
- goto err;
- }
- /*
- * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets|
- * gets reset to 0 if we send more tickets following a post-handshake
- * auth, but |next_ticket_nonce| does not.
- */
- s->sent_tickets++;
- s->next_ticket_nonce++;
- ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
- }
-
- return 1;
- err:
- return 0;
-}
-
-/*
- * In TLSv1.3 this is called from the extensions code, otherwise it is used to
- * create a separate message. Returns 1 on success or 0 on failure.
- */
-int tls_construct_cert_status_body(SSL *s, WPACKET *pkt)
-{
- if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
- || !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
- s->ext.ocsp.resp_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
-int tls_construct_cert_status(SSL *s, WPACKET *pkt)
-{
- if (!tls_construct_cert_status_body(s, pkt)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
-/*
- * tls_process_next_proto reads a Next Protocol Negotiation handshake message.
- * It sets the next_proto member in s if found
- */
-MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt)
-{
- PACKET next_proto, padding;
- size_t next_proto_len;
-
- /*-
- * The payload looks like:
- * uint8 proto_len;
- * uint8 proto[proto_len];
- * uint8 padding_len;
- * uint8 padding[padding_len];
- */
- if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
- || !PACKET_get_length_prefixed_1(pkt, &padding)
- || PACKET_remaining(pkt) > 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) {
- s->ext.npn_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
- ERR_R_INTERNAL_ERROR);
- return MSG_PROCESS_ERROR;
- }
-
- s->ext.npn_len = (unsigned char)next_proto_len;
-
- return MSG_PROCESS_CONTINUE_READING;
-}
-#endif
-
-static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt)
-{
- if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- NULL, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
-MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
-{
- if (PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
- SSL_R_LENGTH_MISMATCH);
- return MSG_PROCESS_ERROR;
- }
-
- if (s->early_data_state != SSL_EARLY_DATA_READING
- && s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
- ERR_R_INTERNAL_ERROR);
- return MSG_PROCESS_ERROR;
- }
-
- /*
- * EndOfEarlyData signals a key change so the end of the message must be on
- * a record boundary.
- */
- if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
- return MSG_PROCESS_ERROR;
- }
-
- s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
- /* SSLfatal() already called */
- return MSG_PROCESS_ERROR;
- }
-
- return MSG_PROCESS_CONTINUE_READING;
-}
+ goto err;
+ }
+ /*
+ * If we are using anti-replay protection then we behave as if
+ * SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
+ * is no point in using full stateless tickets.
+ */
+ if (SSL_IS_TLS13(s)
+ && ((s->options & SSL_OP_NO_TICKET) != 0
+ || (s->max_early_data > 0
+ && (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))) {
+ if (!construct_stateful_ticket(s, pkt, age_add_u.age_add, tick_nonce)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ } else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add,
+ tick_nonce)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ if (SSL_IS_TLS13(s)) {
+ if (!tls_construct_extensions(s, pkt,
+ SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
+ NULL, 0)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ /*
+ * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets|
+ * gets reset to 0 if we send more tickets following a post-handshake
+ * auth, but |next_ticket_nonce| does not.
+ */
+ s->sent_tickets++;
+ s->next_ticket_nonce++;
+ ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
+ }
+
+ return 1;
+ err:
+ return 0;
+}
+
+/*
+ * In TLSv1.3 this is called from the extensions code, otherwise it is used to
+ * create a separate message. Returns 1 on success or 0 on failure.
+ */
+int tls_construct_cert_status_body(SSL *s, WPACKET *pkt)
+{
+ if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
+ || !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
+ s->ext.ocsp.resp_len)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_cert_status(SSL *s, WPACKET *pkt)
+{
+ if (!tls_construct_cert_status_body(s, pkt)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+/*
+ * tls_process_next_proto reads a Next Protocol Negotiation handshake message.
+ * It sets the next_proto member in s if found
+ */
+MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt)
+{
+ PACKET next_proto, padding;
+ size_t next_proto_len;
+
+ /*-
+ * The payload looks like:
+ * uint8 proto_len;
+ * uint8 proto[proto_len];
+ * uint8 padding_len;
+ * uint8 padding[padding_len];
+ */
+ if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
+ || !PACKET_get_length_prefixed_1(pkt, &padding)
+ || PACKET_remaining(pkt) > 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) {
+ s->ext.npn_len = 0;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
+ ERR_R_INTERNAL_ERROR);
+ return MSG_PROCESS_ERROR;
+ }
+
+ s->ext.npn_len = (unsigned char)next_proto_len;
+
+ return MSG_PROCESS_CONTINUE_READING;
+}
+#endif
+
+static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt)
+{
+ if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
+ NULL, 0)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
+ return 1;
+}
+
+MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
+{
+ if (PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
+ SSL_R_LENGTH_MISMATCH);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (s->early_data_state != SSL_EARLY_DATA_READING
+ && s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
+ ERR_R_INTERNAL_ERROR);
+ return MSG_PROCESS_ERROR;
+ }
+
+ /*
+ * EndOfEarlyData signals a key change so the end of the message must be on
+ * a record boundary.
+ */
+ if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
+ SSL_R_NOT_ON_RECORD_BOUNDARY);
+ return MSG_PROCESS_ERROR;
+ }
+
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+}