TLS: support encrypted_server_name extension (0xffce) (esni-01)

Dissect the ESNI TLS 1.3 extension in CH and EE.

Bug: 14984
Change-Id: I95bb5ef0313aefdab7c09dbeb60556d9574c2a00
Reviewed-on: https://code.wireshark.org/review/29817
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
This commit is contained in:
Peter Wu 2018-09-25 00:30:23 +02:00 committed by Alexis La Goutte
parent 1b0167427a
commit 025007ec5f
2 changed files with 96 additions and 1 deletions

View File

@ -1163,6 +1163,7 @@ const value_string tls_hello_extension_types[] = {
{ SSL_HND_HELLO_EXT_GREASE_EAEA, "Reserved (GREASE)" }, /* https://tools.ietf.org/html/draft-ietf-tls-grease */
{ SSL_HND_HELLO_EXT_GREASE_FAFA, "Reserved (GREASE)" }, /* https://tools.ietf.org/html/draft-ietf-tls-grease */
{ SSL_HND_HELLO_EXT_QUIC_TRANSPORT_PARAMETERS, "quic_transports_parameters" }, /* https://tools.ietf.org/html/draft-ietf-quic-tls */
{ SSL_HND_HELLO_EXT_ENCRYPTED_SERVER_NAME, "encrypted_server_name" }, /* https://tools.ietf.org/html/draft-ietf-tls-esni-01 */
{ 0, NULL }
};
@ -7187,6 +7188,59 @@ tls_dissect_sct_list(ssl_common_dissect_t *hf, tvbuff_t *tvb, packet_info *pinfo
return offset;
}
static guint32
ssl_dissect_hnd_hello_ext_esni(ssl_common_dissect_t *hf, tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset, guint32 offset_end,
guint8 hnd_type, SslDecryptSession *ssl _U_)
{
guint32 record_digest_length, encrypted_sni_length;
switch (hnd_type) {
case SSL_HND_CLIENT_HELLO:
/*
* struct {
* CipherSuite suite;
* KeyShareEntry key_share;
* opaque record_digest<0..2^16-1>;
* opaque encrypted_sni<0..2^16-1>;
* } ClientEncryptedSNI;
*/
proto_tree_add_item(tree, hf->hf.esni_suite, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
offset = ssl_dissect_hnd_hello_ext_key_share_entry(hf, tvb, pinfo, tree, offset, offset_end);
/* opaque record_digest<0..2^16-1> */
if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &record_digest_length,
hf->hf.esni_record_digest_length, 0, G_MAXUINT16)) {
return offset_end;
}
offset += 2;
if (record_digest_length > 0) {
proto_tree_add_item(tree, hf->hf.esni_record_digest, tvb, offset, record_digest_length, ENC_NA);
offset += record_digest_length;
}
/* opaque encrypted_sni<0..2^16-1> */
if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &encrypted_sni_length,
hf->hf.esni_encrypted_sni_length, 0, G_MAXUINT16)) {
return offset_end;
}
offset += 2;
if (encrypted_sni_length > 0) {
proto_tree_add_item(tree, hf->hf.esni_encrypted_sni, tvb, offset, encrypted_sni_length, ENC_NA);
offset += encrypted_sni_length;
}
break;
case SSL_HND_ENCRYPTED_EXTENSIONS:
proto_tree_add_item(tree, hf->hf.esni_nonce, tvb, offset, 16, ENC_NA);
offset += 16;
break;
}
return offset;
}
/** TLS Extensions (in Client Hello and Server Hello). }}} */
/* Whether the Content and Handshake Types are valid; handle Protocol Version. {{{ */
@ -8300,6 +8354,9 @@ ssl_dissect_hnd_extension(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *t
case SSL_HND_HELLO_EXT_RENEGOTIATION_INFO:
offset = ssl_dissect_hnd_hello_ext_reneg_info(hf, tvb, pinfo, ext_tree, offset, next_offset);
break;
case SSL_HND_HELLO_EXT_ENCRYPTED_SERVER_NAME:
offset = ssl_dissect_hnd_hello_ext_esni(hf, tvb, pinfo, ext_tree, offset, next_offset, hnd_type, ssl);
break;
default:
proto_tree_add_item(ext_tree, hf->hf.hs_ext_data,
tvb, offset, ext_len, ENC_NA);

View File

@ -139,6 +139,7 @@ typedef enum {
#define SSL_HND_HELLO_EXT_GREASE_FAFA 64250
#define SSL_HND_HELLO_EXT_RENEGOTIATION_INFO 65281 /* 0xFF01 */
#define SSL_HND_HELLO_EXT_QUIC_TRANSPORT_PARAMETERS 65445 /* 0xffa5 draft-ietf-quic-tls-13 */
#define SSL_HND_HELLO_EXT_ENCRYPTED_SERVER_NAME 65486 /* 0xffce draft-ietf-tls-esni-01 */
#define SSL_HND_CERT_URL_TYPE_INDIVIDUAL_CERT 1
#define SSL_HND_CERT_URL_TYPE_PKIPATH 2
@ -865,6 +866,13 @@ typedef struct ssl_common_dissect {
gint hs_ext_quictp_parameter_initial_max_stream_data_bidi_remote;
gint hs_ext_quictp_parameter_initial_max_stream_data_uni;
gint esni_suite;
gint esni_record_digest_length;
gint esni_record_digest;
gint esni_encrypted_sni_length;
gint esni_encrypted_sni;
gint esni_nonce;
/* do not forget to update SSL_COMMON_LIST_T and SSL_COMMON_HF_LIST! */
} hf;
struct {
@ -1080,7 +1088,7 @@ ssl_common_dissect_t name = { \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
}, \
/* ett */ { \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
@ -1935,6 +1943,36 @@ ssl_common_dissect_t name = { \
{ "initial_max_stream_data_uni", prefix ".quic.parameter.initial_max_stream_data_uni", \
FT_UINT32, BASE_DEC, NULL, 0x00, \
"Initial stream maximum data for unidirectional streams parameter", HFILL } \
}, \
{ & name .hf.esni_suite, \
{ "Cipher Suite", prefix ".esni.suite", \
FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0x0, \
"Cipher suite used to encrypt the SNI", HFILL } \
}, \
{ & name .hf.esni_record_digest_length, \
{ "Record Digest Length", prefix ".esni.record_digest_length", \
FT_UINT16, BASE_DEC, NULL, 0x00, \
NULL, HFILL } \
}, \
{ & name .hf.esni_record_digest, \
{ "Record Digest", prefix ".esni.record_digest", \
FT_BYTES, BASE_NONE, NULL, 0x00, \
"Cryptographic hash of the ESNIKeys from which the ESNI key was obtained", HFILL } \
}, \
{ & name .hf.esni_encrypted_sni_length, \
{ "Encrypted SNI Length", prefix ".esni.encrypted_sni_length", \
FT_UINT16, BASE_DEC, NULL, 0x00, \
NULL, HFILL } \
}, \
{ & name .hf.esni_encrypted_sni, \
{ "Encrypted SNI", prefix ".esni.encrypted_sni", \
FT_BYTES, BASE_NONE, NULL, 0x00, \
"The encrypted ClientESNIInner structure", HFILL } \
}, \
{ & name .hf.esni_nonce, \
{ "Nonce", prefix ".esni.nonce", \
FT_BYTES, BASE_NONE, NULL, 0x00, \
"Contents of ClientESNIInner.nonce", HFILL } \
}
/* }}} */