# define SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE 407
# define SSL_F_TLS_CONSTRUCT_CKE_RSA 409
# define SSL_F_TLS_CONSTRUCT_CKE_SRP 410
+# define SSL_F_TLS_CONSTRUCT_CLIENT_ALPN 466
# define SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE 355
+# define SSL_F_TLS_CONSTRUCT_CLIENT_EC_PT_FORMATS 467
+# define SSL_F_TLS_CONSTRUCT_CLIENT_EMS 468
+# define SSL_F_TLS_CONSTRUCT_CLIENT_ETM 469
# define SSL_F_TLS_CONSTRUCT_CLIENT_HELLO 356
# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE 357
+# define SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE 470
+# define SSL_F_TLS_CONSTRUCT_CLIENT_NPN 471
+# define SSL_F_TLS_CONSTRUCT_CLIENT_PADDING 472
+# define SSL_F_TLS_CONSTRUCT_CLIENT_RENEGOTIATE 473
+# define SSL_F_TLS_CONSTRUCT_CLIENT_SCT 474
+# define SSL_F_TLS_CONSTRUCT_CLIENT_SERVER_NAME 475
+# define SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET 476
+# define SSL_F_TLS_CONSTRUCT_CLIENT_SIG_ALGS 477
+# define SSL_F_TLS_CONSTRUCT_CLIENT_SRP 478
+# define SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST 479
+# define SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS 480
+# define SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS 481
+# define SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP 482
# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 358
# define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 443
# define SSL_F_TLS_CONSTRUCT_EXTENSIONS 447
"tls_construct_cke_psk_preamble"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_RSA), "tls_construct_cke_rsa"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CKE_SRP), "tls_construct_cke_srp"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_ALPN), "tls_construct_client_alpn"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE),
"tls_construct_client_certificate"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_EC_PT_FORMATS),
+ "tls_construct_client_ec_pt_formats"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_EMS), "tls_construct_client_ems"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_ETM), "tls_construct_client_etm"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO),
"tls_construct_client_hello"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE),
"tls_construct_client_key_exchange"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE),
+ "tls_construct_client_key_share"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_NPN), "tls_construct_client_npn"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_PADDING),
+ "tls_construct_client_padding"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_RENEGOTIATE),
+ "tls_construct_client_renegotiate"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SCT), "tls_construct_client_sct"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SERVER_NAME),
+ "tls_construct_client_server_name"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET),
+ "tls_construct_client_session_ticket"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SIG_ALGS),
+ "tls_construct_client_sig_algs"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SRP), "tls_construct_client_srp"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST),
+ "tls_construct_client_status_request"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS),
+ "tls_construct_client_supported_groups"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS),
+ "tls_construct_client_supported_versions"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP),
+ "tls_construct_client_use_srtp"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY),
"tls_construct_client_verify"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS),
__owur int tls1_get_curvelist(SSL *s, int sess, const unsigned char **pcurves,
size_t *num_curves);
-__owur int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al);
void ssl_set_default_md(SSL *s);
__owur int tls1_set_server_sigalgs(SSL *s);
__owur int ssl_check_clienthello_tlsext_late(SSL *s, int *al);
__owur int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt);
-__owur int ssl_prepare_clienthello_tlsext(SSL *s);
__owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts,
size_t numexts,
unsigned int type);
tls_parse_client_renegotiate,
tls_parse_server_renegotiate,
tls_construct_server_renegotiate,
- NULL,
+ tls_construct_client_renegotiate,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED
| EXT_TLS1_2_AND_BELOW_ONLY
},
tls_parse_client_server_name,
tls_parse_server_server_name,
tls_construct_server_server_name,
- NULL,
+ tls_construct_client_server_name,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
},
tls_parse_client_srp,
NULL,
NULL,
- NULL,
+ tls_construct_client_srp,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
},
#endif
tls_parse_client_ec_pt_formats,
tls_parse_server_ec_pt_formats,
tls_construct_server_ec_pt_formats,
- NULL,
+ tls_construct_client_ec_pt_formats,
EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
},
{
tls_parse_client_supported_groups,
NULL,
NULL /* TODO(TLS1.3): Need to add this */,
- NULL,
+ tls_construct_client_supported_groups,
EXT_CLIENT_HELLO
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
},
tls_parse_client_session_ticket,
tls_parse_server_session_ticket,
tls_construct_server_session_ticket,
- NULL,
+ tls_construct_client_session_ticket,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
},
{
tls_parse_client_sig_algs,
NULL,
NULL,
- NULL,
+ tls_construct_client_sig_algs,
EXT_CLIENT_HELLO
},
+#ifndef OPENSSL_NO_OCSP
{
TLSEXT_TYPE_status_request,
tls_parse_client_status_request,
tls_parse_server_status_request,
tls_construct_server_status_request,
- NULL,
+ tls_construct_client_status_request,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_CERTIFICATE
},
+#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
{
TLSEXT_TYPE_next_proto_neg,
tls_parse_client_npn,
tls_parse_server_npn,
tls_construct_server_next_proto_neg,
- NULL,
+ tls_construct_client_npn,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
},
#endif
tls_parse_client_alpn,
tls_parse_server_alpn,
tls_construct_server_alpn,
- NULL,
+ tls_construct_client_alpn,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS
},
tls_parse_client_use_srtp,
tls_parse_server_use_srtp,
tls_construct_server_use_srtp,
- NULL,
+ tls_construct_client_use_srtp,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY
},
tls_parse_client_etm,
tls_parse_server_etm,
tls_construct_server_etm,
- NULL,
+ tls_construct_client_etm,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
},
#ifndef OPENSSL_NO_CT
NULL,
tls_parse_server_sct,
NULL,
- NULL,
+ tls_construct_client_sct,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
| EXT_TLS1_3_CERTIFICATE
},
tls_parse_client_ems,
tls_parse_server_ems,
tls_construct_server_ems,
- NULL,
+ tls_construct_client_ems,
EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
},
{
NULL,
NULL,
NULL,
- NULL,
- EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY
- },
- {
- TLSEXT_TYPE_padding,
- /* We send this, but don't read it */
- NULL,
- NULL,
- NULL,
- NULL,
- EXT_CLIENT_HELLO
+ tls_construct_client_supported_versions,
+ EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY | EXT_TLS1_3_ONLY
},
{
TLSEXT_TYPE_key_share,
tls_parse_client_key_share,
tls_parse_server_key_share,
tls_construct_server_key_share,
- NULL,
+ tls_construct_client_key_share,
EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO
| EXT_TLS1_3_HELLO_RETRY_REQUEST | EXT_TLS_IMPLEMENTATION_ONLY
| EXT_TLS1_3_ONLY
tls_construct_server_cryptopro_bug,
NULL,
EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
+ },
+ {
+ /* Last in the list because it must be added as the last extension */
+ TLSEXT_TYPE_padding,
+ /* We send this, but don't read it */
+ NULL,
+ NULL,
+ NULL,
+ tls_construct_client_padding,
+ EXT_CLIENT_HELLO
}
};
{
size_t loop;
int addcustom = 0;
+ int min_version, max_version = 0, reason;
/*
* Normally if something goes wrong during construction its an internal
return 0;
}
+ if ((context & EXT_CLIENT_HELLO) != 0) {
+ reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
+ if (reason != 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, reason);
+ return 0;
+ }
+ }
+
+ /* Add custom extensions first */
+ if ((context & EXT_CLIENT_HELLO) != 0) {
+ custom_ext_init(&s->cert->cli_ext);
+ addcustom = 1;
+ } else if ((context & EXT_TLS1_2_SERVER_HELLO) != 0) {
+ /*
+ * We already initialised the custom extensions during ClientHello
+ * parsing.
+ *
+ * TODO(TLS1.3): We're going to need a new custom extension mechanism
+ * for TLS1.3, so that custom extensions can specify which of the
+ * multiple message they wish to add themselves to.
+ */
+ addcustom = 1;
+ }
+
+ if (addcustom && !custom_ext_add(s, s->server, pkt, al)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
for (loop = 0; loop < OSSL_NELEM(ext_defs); loop++) {
int (*construct)(SSL *s, WPACKET *pkt, int *al);
|| (!SSL_IS_TLS13(s)
&& (ext_defs[loop].context & EXT_TLS1_3_ONLY) != 0
&& (context & EXT_CLIENT_HELLO) == 0)
+ || ((ext_defs[loop].context & EXT_TLS1_3_ONLY) != 0
+ && (context & EXT_CLIENT_HELLO) != 0
+ && (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION))
|| construct == NULL)
continue;
return 0;
}
- /* Add custom extensions */
- if ((context & EXT_CLIENT_HELLO) != 0) {
- custom_ext_init(&s->cert->cli_ext);
- addcustom = 1;
- } else if ((context & EXT_TLS1_2_SERVER_HELLO) != 0) {
- /*
- * We already initialised the custom extensions during ClientHello
- * parsing.
- *
- * TODO(TLS1.3): We're going to need a new custom extension mechanism
- * for TLS1.3, so that custom extensions can specify which of the
- * multiple message they wish to add themselves to.
- */
- addcustom = 1;
- }
-
- if (addcustom && !custom_ext_add(s, s->server, pkt, al)) {
- SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
if (!WPACKET_close(pkt)) {
SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
return 0;
*/
#include <assert.h>
+#include <openssl/ocsp.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
+int tls_construct_client_renegotiate(SSL *s, WPACKET *pkt, int *al)
+{
+ /* Add RI if renegotiating */
+ if (!s->renegotiate)
+ return 1;
+
+ 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_RENEGOTIATE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_client_server_name(SSL *s, WPACKET *pkt, int *al)
+{
+ if (s->tlsext_hostname == NULL)
+ return 1;
+
+ /* 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->tlsext_hostname,
+ strlen(s->tlsext_hostname))
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SERVER_NAME, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRP
+int tls_construct_client_srp(SSL *s, WPACKET *pkt, int *al)
+{
+ /* Add SRP username if there is one */
+ if (s->srp_ctx.login == NULL)
+ return 1;
+
+ 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SRP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+static int use_ecc(SSL *s)
+{
+ int using_ecc = 0;
+ int i;
+ 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_get_ciphers(s);
+
+ for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); 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) {
+ using_ecc = 1;
+ break;
+ }
+ }
+
+ return using_ecc;
+}
+
+int tls_construct_client_ec_pt_formats(SSL *s, WPACKET *pkt, int *al)
+{
+ const unsigned char *pformats;
+ size_t num_formats;
+
+ if (!use_ecc(s))
+ return 1;
+
+ /* 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int tls_construct_client_supported_groups(SSL *s, WPACKET *pkt, int *al)
+{
+ const unsigned char *pcurves = NULL, *pcurvestmp;
+ size_t num_curves = 0, i;
+
+ if (!use_ecc(s))
+ return 1;
+
+ /*
+ * Add TLS extension supported_groups to the ClientHello message
+ */
+ /* TODO(TLS1.3): Add support for DHE groups */
+ pcurves = s->tlsext_supportedgroupslist;
+ if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ pcurvestmp = pcurves;
+
+ 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ /* Copy curve ID if supported */
+ for (i = 0; i < num_curves; i++, pcurvestmp += 2) {
+ if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
+ if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0])
+ || !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_GROUPS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+int tls_construct_client_session_ticket(SSL *s, WPACKET *pkt, int *al)
+{
+ size_t ticklen;
+
+ if (!tls_use_ticket(s))
+ return 1;
+
+ if (!s->new_session && s->session != NULL
+ && s->session->tlsext_tick != NULL) {
+ ticklen = s->session->tlsext_ticklen;
+ } else if (s->session && s->tlsext_session_ticket != NULL
+ && s->tlsext_session_ticket->data != NULL) {
+ ticklen = s->tlsext_session_ticket->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (s->session->tlsext_tick == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ memcpy(s->session->tlsext_tick,
+ s->tlsext_session_ticket->data, ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ } else {
+ ticklen = 0;
+ }
+
+ if (ticklen == 0 && s->tlsext_session_ticket != NULL &&
+ s->tlsext_session_ticket->data == NULL)
+ return 1;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
+ || !WPACKET_sub_memcpy_u16(pkt, s->session->tlsext_tick, ticklen)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_client_sig_algs(SSL *s, WPACKET *pkt, int *al)
+{
+ size_t salglen;
+ const unsigned char *salg;
+
+ if (!SSL_CLIENT_USE_SIGALGS(s))
+ return 1;
+
+ salglen = tls12_get_psigalgs(s, &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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SIG_ALGS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_OCSP
+int tls_construct_client_status_request(SSL *s, WPACKET *pkt, int *al)
+{
+ int i;
+
+ if (s->tlsext_status_type != TLSEXT_STATUSTYPE_ocsp)
+ return 1;
+
+ 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) {
+ unsigned char *idbytes;
+ int idlen;
+ OCSP_RESPID *id;
+
+ id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+ 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) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (!WPACKET_close(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (s->tlsext_ocsp_exts) {
+ unsigned char *extbytes;
+ int extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
+
+ if (extlen < 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
+ || i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &extbytes)
+ != extlen) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+int tls_construct_client_npn(SSL *s, WPACKET *pkt, int *al)
+{
+ if (s->ctx->next_proto_select_cb == NULL || s->s3->tmp.finish_md_len != 0)
+ return 1;
+
+ /*
+ * 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_NPN, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+int tls_construct_client_alpn(SSL *s, WPACKET *pkt, int *al)
+{
+ s->s3->alpn_sent = 0;
+
+ /*
+ * finish_md_len is non-zero during a renegotiation, so
+ * this avoids sending ALPN during the renegotiation
+ */
+ if (s->alpn_client_proto_list == NULL || s->s3->tmp.finish_md_len != 0)
+ return 1;
+
+ 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->alpn_client_proto_list,
+ s->alpn_client_proto_list_len)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_ALPN, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ s->s3->alpn_sent = 1;
+
+ return 1;
+}
+
+
+#ifndef OPENSSL_NO_SRTP
+int tls_construct_client_use_srtp(SSL *s, WPACKET *pkt, int *al)
+{
+ STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
+ SRTP_PROTECTION_PROFILE *prof;
+ int i, ct;
+
+ if (clnt == NULL)
+ return 1;
+
+ 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ ct = sk_SRTP_PROTECTION_PROFILE_num(clnt);
+ for (i = 0; i < ct; i++) {
+ prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
+ if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (!WPACKET_close(pkt)
+ /* Add an empty use_mki value */
+ || !WPACKET_put_bytes_u8(pkt, 0)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_USE_SRTP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+int tls_construct_client_etm(SSL *s, WPACKET *pkt, int *al)
+{
+ if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
+ return 1;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_ETM, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_CT
+int tls_construct_client_sct(SSL *s, WPACKET *pkt, int *al)
+{
+ if (s->ct_validation_callback == NULL)
+ return 1;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SCT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+int tls_construct_client_ems(SSL *s, WPACKET *pkt, int *al)
+{
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_EMS, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_client_supported_versions(SSL *s, WPACKET *pkt, int *al)
+{
+ int currv, min_version, max_version, reason;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u8(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
+ if (reason != 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS, reason);
+ return 0;
+ }
+
+ /*
+ * TODO(TLS1.3): There is some discussion on the TLS list as to wheter
+ * we should include versions <TLS1.2. For the moment we do. To be
+ * reviewed later.
+ */
+ for (currv = max_version; currv >= min_version; currv--) {
+ /* TODO(TLS1.3): Remove this first if clause prior to release!! */
+ if (currv == TLS1_3_VERSION) {
+ if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else if (!WPACKET_put_bytes_u16(pkt, currv)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int tls_construct_client_key_share(SSL *s, WPACKET *pkt, int *al)
+{
+ size_t i, sharessent = 0, num_curves = 0;
+ const unsigned char *pcurves = NULL;
+
+ /* 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)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ pcurves = s->tlsext_supportedgroupslist;
+ if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /*
+ * TODO(TLS1.3): Make the number of key_shares sent configurable. For
+ * now, just send one
+ */
+ for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) {
+ unsigned char *encodedPoint = NULL;
+ unsigned int curve_id = 0;
+ EVP_PKEY *key_share_key = NULL;
+ size_t encodedlen;
+
+ if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
+ continue;
+
+ if (s->s3->tmp.pkey != NULL) {
+ /* Shouldn't happen! */
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Generate a key for this key_share */
+ curve_id = (pcurves[0] << 8) | pcurves[1];
+ key_share_key = ssl_generate_pkey_curve(curve_id);
+ if (key_share_key == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_EVP_LIB);
+ return 0;
+ }
+
+ /* Encode the public key. */
+ encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
+ &encodedPoint);
+ if (encodedlen == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_EC_LIB);
+ EVP_PKEY_free(key_share_key);
+ return 0;
+ }
+
+ /* Create KeyShareEntry */
+ if (!WPACKET_put_bytes_u16(pkt, curve_id)
+ || !WPACKET_sub_memcpy_u16(pkt, encodedPoint, encodedlen)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(key_share_key);
+ OPENSSL_free(encodedPoint);
+ return 0;
+ }
+
+ /*
+ * 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->group_id = curve_id;
+ s->s3->tmp.pkey = key_share_key;
+ sharessent++;
+ OPENSSL_free(encodedPoint);
+ }
+
+ if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+int tls_construct_client_padding(SSL *s, WPACKET *pkt, int *al)
+{
+ unsigned char *padbytes;
+ size_t hlen;
+
+ if ((s->options & SSL_OP_TLSEXT_PADDING) == 0)
+ return 1;
+
+ /*
+ * Add padding to workaround bugs in F5 terminators. See
+ * https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this
+ * code works out the length of all existing extensions it MUST always
+ * appear last.
+ */
+ if (!WPACKET_get_total_written(pkt, &hlen)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_PADDING, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (hlen > 0xff && hlen < 0x200) {
+ hlen = 0x200 - hlen;
+ if (hlen >= 4)
+ hlen -= 4;
+ else
+ hlen = 0;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
+ || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_PADDING, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ memset(padbytes, 0, hlen);
+ }
+
+ return 1;
+}
+
/*
* Parse the server's renegotiation binding and abort if it's not right
*/
return 1;
}
+#ifndef OPENSSL_NO_OCSP
int tls_parse_server_status_request(SSL *s, PACKET *pkt, int *al)
{
/*
return 1;
}
+#endif
#ifndef OPENSSL_NO_CT
return 1;
}
+#ifndef OPENSSL_NO_OCSP
int tls_parse_client_status_request(SSL *s, PACKET *pkt, int *al)
{
if (!PACKET_get_1(pkt, (unsigned int *)&s->tlsext_status_type)) {
*al = SSL_AD_DECODE_ERROR;
return 0;
}
-#ifndef OPENSSL_NO_OCSP
+
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
const unsigned char *ext_data;
PACKET responder_id_list, exts;
return 0;
}
}
- } else
-#endif
- {
+ } else {
/*
* We don't know what to do with any other type so ignore it.
*/
return 1;
}
+#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_parse_client_npn(SSL *s, PACKET *pkt, int *al)
return 1;
}
+#ifndef OPENSSL_NO_OCSP
int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al)
{
if (!s->tlsext_status_expected)
return 1;
}
+#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
}
/* TLS extensions */
- if (ssl_prepare_clienthello_tlsext(s) <= 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
- return 0;
- }
- if (!WPACKET_start_sub_packet_u16(pkt)
- /*
- * If extensions are of zero length then we don't even add the
- * extensions length bytes
- */
- || !WPACKET_set_flags(pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)
- || !ssl_add_clienthello_tlsext(s, pkt, &al)
- || !WPACKET_close(pkt)) {
+ if (!tls_construct_extensions(s, pkt, EXT_CLIENT_HELLO, &al)) {
ssl3_send_alert(s, SSL3_AL_FATAL, al);
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
return 0;
#endif
int tls_parse_client_session_ticket(SSL *s, PACKET *pkt, int *al);
int tls_parse_client_sig_algs(SSL *s, PACKET *pkt, int *al);
+#ifndef OPENSSL_NO_OCSP
int tls_parse_client_status_request(SSL *s, PACKET *pkt, int *al);
+#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_parse_client_npn(SSL *s, PACKET *pkt, int *al);
#endif
int tls_construct_server_renegotiate(SSL *s, WPACKET *pkt, int *al);
int tls_construct_server_server_name(SSL *s, WPACKET *pkt, int *al);
+#ifndef OPENSSL_NO_EC
int tls_construct_server_ec_pt_formats(SSL *s, WPACKET *pkt, int *al);
+#endif
int tls_construct_server_session_ticket(SSL *s, WPACKET *pkt, int *al);
+#ifndef OPENSSL_NO_OCSP
int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al);
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_construct_server_next_proto_neg(SSL *s, WPACKET *pkt, int *al);
+#endif
int tls_construct_server_alpn(SSL *s, WPACKET *pkt, int *al);
+#ifndef OPENSSL_NO_SRTP
int tls_construct_server_use_srtp(SSL *s, WPACKET *pkt, int *al);
+#endif
int tls_construct_server_etm(SSL *s, WPACKET *pkt, int *al);
int tls_construct_server_ems(SSL *s, WPACKET *pkt, int *al);
int tls_construct_server_key_share(SSL *s, WPACKET *pkt, int *al);
int tls_construct_server_cryptopro_bug(SSL *s, WPACKET *pkt, int *al);
/* Client Extension processing */
+int tls_construct_client_renegotiate(SSL *s, WPACKET *pkt, int *al);
+int tls_construct_client_server_name(SSL *s, WPACKET *pkt, int *al);
+#ifndef OPENSSL_NO_SRP
+int tls_construct_client_srp(SSL *s, WPACKET *pkt, int *al);
+#endif
+#ifndef OPENSSL_NO_EC
+int tls_construct_client_ec_pt_formats(SSL *s, WPACKET *pkt, int *al);
+int tls_construct_client_supported_groups(SSL *s, WPACKET *pkt, int *al);
+#endif
+int tls_construct_client_session_ticket(SSL *s, WPACKET *pkt, int *al);
+int tls_construct_client_sig_algs(SSL *s, WPACKET *pkt, int *al);
+#ifndef OPENSSL_NO_OCSP
+int tls_construct_client_status_request(SSL *s, WPACKET *pkt, int *al);
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+int tls_construct_client_npn(SSL *s, WPACKET *pkt, int *al);
+#endif
+int tls_construct_client_alpn(SSL *s, WPACKET *pkt, int *al);
+#ifndef OPENSSL_NO_SRTP
+int tls_construct_client_use_srtp(SSL *s, WPACKET *pkt, int *al);
+#endif
+int tls_construct_client_etm(SSL *s, WPACKET *pkt, int *al);
+#ifndef OPENSSL_NO_CT
+int tls_construct_client_sct(SSL *s, WPACKET *pkt, int *al);
+#endif
+int tls_construct_client_ems(SSL *s, WPACKET *pkt, int *al);
+int tls_construct_client_supported_versions(SSL *s, WPACKET *pkt, int *al);
+int tls_construct_client_key_share(SSL *s, WPACKET *pkt, int *al);
+int tls_construct_client_padding(SSL *s, WPACKET *pkt, int *al);
int tls_parse_server_renegotiate(SSL *s, PACKET *pkt, int *al);
int tls_parse_server_server_name(SSL *s, PACKET *pkt, int *al);
#ifndef OPENSSL_NO_EC
int tls_parse_server_ec_pt_formats(SSL *s, PACKET *pkt, int *al);
#endif
int tls_parse_server_session_ticket(SSL *s, PACKET *pkt, int *al);
+#ifndef OPENSSL_NO_OCSP
int tls_parse_server_status_request(SSL *s, PACKET *pkt, int *al);
+#endif
#ifndef OPENSSL_NO_CT
int tls_parse_server_sct(SSL *s, PACKET *pkt, int *al);
#endif
return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
}
-int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al)
-{
-#ifndef OPENSSL_NO_EC
- const unsigned char *pcurves = NULL;
- size_t num_curves = 0;
- int using_ecc = 0;
- int min_version, max_version, reason;
-
- /* See if we support any ECC ciphersuites */
- if ((s->version >= TLS1_VERSION && s->version <= TLS1_3_VERSION)
- || SSL_IS_DTLS(s)) {
- int i;
- unsigned long alg_k, alg_a;
- STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);
-
- for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); 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) {
- using_ecc = 1;
- break;
- }
- }
- }
-#else
- if (SSL_IS_TLS13(s)) {
- /* Shouldn't happen! */
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-#endif
-
- /* Add RI if renegotiating */
- if (s->renegotiate) {
- 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- /* Only add RI for SSLv3 */
- if (s->client_version == SSL3_VERSION)
- goto done;
-
- if (s->tlsext_hostname != NULL) {
- /* 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->tlsext_hostname,
- strlen(s->tlsext_hostname))
- || !WPACKET_close(pkt)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#ifndef OPENSSL_NO_SRP
- /* Add SRP username if there is one */
- if (s->srp_ctx.login != NULL) {
- 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
-#ifndef OPENSSL_NO_EC
- if (using_ecc) {
- /*
- * Add TLS extension ECPointFormats to the ClientHello message
- */
- const unsigned char *pformats, *pcurvestmp;
- size_t num_formats;
- size_t i;
-
- 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * Add TLS extension supported_groups to the ClientHello message
- */
- /* TODO(TLS1.3): Add support for DHE groups */
- pcurves = s->tlsext_supportedgroupslist;
- if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- pcurvestmp = pcurves;
-
- 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- /* Copy curve ID if supported */
- for (i = 0; i < num_curves; i++, pcurvestmp += 2) {
- if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
- if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0])
- || !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif /* OPENSSL_NO_EC */
-
- if (tls_use_ticket(s)) {
- size_t ticklen;
- if (!s->new_session && s->session && s->session->tlsext_tick)
- ticklen = s->session->tlsext_ticklen;
- else if (s->session && s->tlsext_session_ticket &&
- s->tlsext_session_ticket->data) {
- ticklen = s->tlsext_session_ticket->length;
- s->session->tlsext_tick = OPENSSL_malloc(ticklen);
- if (s->session->tlsext_tick == NULL) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- memcpy(s->session->tlsext_tick,
- s->tlsext_session_ticket->data, ticklen);
- s->session->tlsext_ticklen = ticklen;
- } else
- ticklen = 0;
- if (ticklen == 0 && s->tlsext_session_ticket &&
- s->tlsext_session_ticket->data == NULL)
- goto skip_ext;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
- || !WPACKET_sub_memcpy_u16(pkt, s->session->tlsext_tick,
- ticklen)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- skip_ext:
-
- if (SSL_CLIENT_USE_SIGALGS(s)) {
- size_t salglen;
- const unsigned char *salg;
-
- salglen = tls12_get_psigalgs(s, &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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#ifndef OPENSSL_NO_OCSP
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
- int i;
-
- 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) {
- unsigned char *idbytes;
- int idlen;
- OCSP_RESPID *id;
-
- id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
- 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) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt)
- || !WPACKET_start_sub_packet_u16(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (s->tlsext_ocsp_exts) {
- unsigned char *extbytes;
- int extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
-
- if (extlen < 0) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
- || i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &extbytes)
- != extlen) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
- if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) {
- /*
- * 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
- /*
- * finish_md_len is non-zero during a renegotiation, so
- * this avoids sending ALPN during the renegotiation
- * (see longer comment below)
- */
- if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) {
- 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->alpn_client_proto_list,
- s->alpn_client_proto_list_len)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->s3->alpn_sent = 1;
- }
-#ifndef OPENSSL_NO_SRTP
- if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) {
- STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
- SRTP_PROTECTION_PROFILE *prof;
- int i, ct;
-
- 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- ct = sk_SRTP_PROTECTION_PROFILE_num(clnt);
- for (i = 0; i < ct; i++) {
- prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
- if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt)
- /* Add an empty use_mki value */
- || !WPACKET_put_bytes_u8(pkt, 0)
- || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
- custom_ext_init(&s->cert->cli_ext);
- /* Add custom TLS Extensions to ClientHello */
- if (!custom_ext_add(s, 0, pkt, al)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) {
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
-#ifndef OPENSSL_NO_CT
- if (s->ct_validation_callback != NULL) {
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-#endif
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
- || !WPACKET_put_bytes_u16(pkt, 0)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- reason = ssl_get_client_min_max_version(s, &min_version, &max_version);
- if (reason != 0) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, reason);
- return 0;
- }
-
- /* TLS1.3 specific extensions */
- if (!SSL_IS_DTLS(s) && max_version >= TLS1_3_VERSION) {
- int currv;
- size_t i, sharessent = 0;
-
- /* TODO(TLS1.3): Should we add this extension for versions < TLS1.3? */
- /* supported_versions extension */
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
- || !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_start_sub_packet_u8(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * TODO(TLS1.3): There is some discussion on the TLS list as to wheter
- * we should include versions <TLS1.2. For the moment we do. To be
- * reviewed later.
- */
- for (currv = max_version; currv >= min_version; currv--) {
- /* TODO(TLS1.3): Remove this first if clause prior to release!! */
- if (currv == TLS1_3_VERSION) {
- if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- } else if (!WPACKET_put_bytes_u16(pkt, currv)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 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)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * TODO(TLS1.3): Make the number of key_shares sent configurable. For
- * now, just send one
- */
- for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) {
- unsigned char *encodedPoint = NULL;
- unsigned int curve_id = 0;
- EVP_PKEY *key_share_key = NULL;
- size_t encodedlen;
-
- if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
- continue;
-
- if (s->s3->tmp.pkey != NULL) {
- /* Shouldn't happen! */
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* Generate a key for this key_share */
- curve_id = (pcurves[0] << 8) | pcurves[1];
- key_share_key = ssl_generate_pkey_curve(curve_id);
- if (key_share_key == NULL) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB);
- return 0;
- }
-
- /* Encode the public key. */
- encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
- &encodedPoint);
- if (encodedlen == 0) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EC_LIB);
- EVP_PKEY_free(key_share_key);
- return 0;
- }
-
- /* Create KeyShareEntry */
- if (!WPACKET_put_bytes_u16(pkt, curve_id)
- || !WPACKET_sub_memcpy_u16(pkt, encodedPoint, encodedlen)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT,
- ERR_R_INTERNAL_ERROR);
- EVP_PKEY_free(key_share_key);
- OPENSSL_free(encodedPoint);
- return 0;
- }
-
- /*
- * 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->group_id = curve_id;
- s->s3->tmp.pkey = key_share_key;
- sharessent++;
- OPENSSL_free(encodedPoint);
- }
- if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
-
- /*
- * Add padding to workaround bugs in F5 terminators. See
- * https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this
- * code works out the length of all existing extensions it MUST always
- * appear last.
- */
- if (s->options & SSL_OP_TLSEXT_PADDING) {
- unsigned char *padbytes;
- size_t hlen;
-
- if (!WPACKET_get_total_written(pkt, &hlen)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (hlen > 0xff && hlen < 0x200) {
- hlen = 0x200 - hlen;
- if (hlen >= 4)
- hlen -= 4;
- else
- hlen = 0;
-
- if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
- || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- memset(padbytes, 0, hlen);
- }
- }
-
- done:
- return 1;
-}
-
-int ssl_prepare_clienthello_tlsext(SSL *s)
-{
- s->s3->alpn_sent = 0;
- return 1;
-}
-
/* Initialise digests to default values */
void ssl_set_default_md(SSL *s)
{