This is required for the later addition of resumption support.
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2259)
# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE 470
# define SSL_F_TLS_CONSTRUCT_CTOS_NPN 471
# define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 472
+# define SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES 509
# define SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE 473
# define SSL_F_TLS_CONSTRUCT_CTOS_SCT 474
# define SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME 475
/* As defined for TLS1.3 */
# define TLSEXT_TYPE_key_share 40
# define TLSEXT_TYPE_supported_versions 43
+# define TLSEXT_TYPE_psk_kex_modes 45
/* Temporary extension type */
# define TLSEXT_TYPE_renegotiate 0xff01
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_NPN), "tls_construct_ctos_npn"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_PADDING),
"tls_construct_ctos_padding"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES),
+ "tls_construct_ctos_psk_kex_modes"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE),
"tls_construct_ctos_renegotiate"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_SCT), "tls_construct_ctos_sct"},
*/
unsigned char *npn;
size_t npn_len;
+
+ /* The selected PSK key exchange mode */
+ int psk_kex_mode;
} ext;
/*-
TLSEXT_IDX_signed_certificate_timestamp,
TLSEXT_IDX_extended_master_secret,
TLSEXT_IDX_supported_versions,
+ TLSEXT_IDX_psk_kex_modes,
TLSEXT_IDX_key_share,
TLSEXT_IDX_cryptopro_bug,
TLSEXT_IDX_padding
#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef
#define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded
+/* Known PSK key exchange modes */
+#define TLSEXT_KEX_MODE_KE 0x00
+#define TLSEXT_KEX_MODE_KE_DHE 0x01
+
+/*
+ * Internal representations of key exchange modes
+ */
+#define TLSEXT_KEX_MODE_FLAG_NONE 0
+#define TLSEXT_KEX_MODE_FLAG_KE 1
+#define TLSEXT_KEX_MODE_FLAG_KE_DHE 2
+
#define SIGID_IS_PSS(sigid) ((sigid) == TLSEXT_SIGALG_rsa_pss_sha256 \
|| (sigid) == TLSEXT_SIGALG_rsa_pss_sha384 \
|| (sigid) == TLSEXT_SIGALG_rsa_pss_sha512)
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, int *al);
+static int init_psk_kex_modes(SSL *s, unsigned int context);
#ifndef OPENSSL_NO_SRTP
static int init_srtp(SSL *s, unsigned int context);
#endif
/* Processed inline as part of version selection */
NULL, NULL, NULL, tls_construct_ctos_supported_versions, NULL
},
+ {
+ /* Must be before key_share */
+ TLSEXT_TYPE_psk_kex_modes,
+ EXT_CLIENT_HELLO | EXT_TLS_IMPLEMENTATION_ONLY | EXT_TLS1_3_ONLY,
+ init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL,
+ tls_construct_ctos_psk_kex_modes, NULL
+ },
{
/*
* Must be in this list after supported_groups. We need that to have
return 1;
}
+
+static int init_psk_kex_modes(SSL *s, unsigned int context)
+{
+ s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
+
+ return 1;
+}
return 1;
}
+/*
+ * Construct a psk_kex_modes extension. We only have two modes we know about
+ * at this stage, so we send both.
+ */
+int tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt, X509 *x,
+ size_t chainidx, int *al)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ /*
+ * TODO(TLS1.3): Do we want this list to be configurable? For now we always
+ * just send both supported modes
+ */
+ 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)
+ || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE)
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
int tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
int *al)
{
}
#endif
+/*
+ * 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.
+ * If a failure occurs then |*al| is set to an appropriate alert value.
+ */
+int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
+ int *al)
+{
+#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) {
+ *al = SSL_AD_DECODE_ERROR;
+ 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->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, X509 *x, size_t chainidx,
int *al);
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, X509 *x, size_t chainidx, int *al);
+int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
+ int *al);
int tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt, X509 *x,
size_t chainidx, int *al);
size_t chainidx, int *al);
int tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
int *al);
+int tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt, X509 *x,
+ size_t chainidx, int *al);
int tls_construct_ctos_padding(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx,
int *al);
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, X509 *x, size_t chainidx,
{TLSEXT_TYPE_server_authz, "server_authz"},
{TLSEXT_TYPE_cert_type, "cert_type"},
{TLSEXT_TYPE_key_share, "key_share"},
+ {TLSEXT_TYPE_psk_kex_modes, "psk_key_exchange_modes"},
{TLSEXT_TYPE_supported_groups, "supported_groups"},
{TLSEXT_TYPE_ec_point_formats, "ec_point_formats"},
{TLSEXT_TYPE_srp, "srp"},
{66, "ecdsa_fixed_ecdh"}
};
+static ssl_trace_tbl ssl_psk_kex_modes_tbl[] = {
+ {TLSEXT_KEX_MODE_KE, "psk_ke"},
+ {TLSEXT_KEX_MODE_KE_DHE, "psk_dhe_ke"}
+};
+
static ssl_trace_tbl ssl_crypto_tbl[] = {
{TLS1_RT_CRYPTO_PREMASTER, "Premaster Secret"},
{TLS1_RT_CRYPTO_CLIENT_RANDOM, "Client Random"},
return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 2,
ssl_version_tbl);
+ case TLSEXT_TYPE_psk_kex_modes:
+ if (extlen < 1)
+ return 0;
+ xlen = ext[0];
+ if (extlen != xlen + 1)
+ return 0;
+ return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1,
+ ssl_psk_kex_modes_tbl);
+
default:
BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2);
}
checkhandshake::DEFAULT_EXTENSIONS],
[TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
checkhandshake::DEFAULT_EXTENSIONS],
+ [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK_KEX_MODES,
+ checkhandshake::DEFAULT_EXTENSIONS],
[TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
checkhandshake::DEFAULT_EXTENSIONS],
EXT_SESSION_TICKET => 35,
EXT_KEY_SHARE => 40,
EXT_SUPPORTED_VERSIONS => 43,
+ EXT_PSK_KEX_MODES => 45,
EXT_RENEGOTIATE => 65281,
EXT_NPN => 13172,
# This extension is an unofficial extension only ever written by OpenSSL