TLS13: prepare for early data trial decryption
[metze/wireshark/wip.git] / epan / dissectors / packet-ssl-utils.c
index 725aedb6f4821eada64927a50f4d94dd537d4022..81b7e17b711a4090f16375914f68ca4f68f97bfa 100644 (file)
@@ -9,19 +9,7 @@
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 #include "config.h"
@@ -103,6 +91,8 @@ const value_string ssl_versions[] = {
     { 0x7F14,               "TLS 1.3 (draft 20)" },
     { 0x7F15,               "TLS 1.3 (draft 21)" },
     { 0x7F16,               "TLS 1.3 (draft 22)" },
+    { 0x7F17,               "TLS 1.3 (draft 23)" },
+    { 0x7F18,               "TLS 1.3 (draft 24)" },
     { DTLSV1DOT0_OPENSSL_VERSION, "DTLS 1.0 (OpenSSL pre 0.9.8f)" },
     { DTLSV1DOT0_VERSION,   "DTLS 1.0" },
     { DTLSV1DOT2_VERSION,   "DTLS 1.2" },
@@ -1212,7 +1202,7 @@ const value_string tls_hello_extension_types[] = {
     { SSL_HND_HELLO_EXT_CACHED_INFO, "cached_info" }, /* RFC 7924 */
     { SSL_HND_HELLO_EXT_QUIC_TRANSPORT_PARAMETERS, "quic_transports_parameters" }, /* https://tools.ietf.org/html/draft-ietf-quic-tls */
     { SSL_HND_HELLO_EXT_SESSION_TICKET_TLS, "SessionTicket TLS" }, /* RFC 4507 */
-    { SSL_HND_HELLO_EXT_KEY_SHARE, "key_share" }, /* TLS 1.3 https://tools.ietf.org/html/draft-ietf-tls-tls13 */
+    { SSL_HND_HELLO_EXT_KEY_SHARE_OLD, "Reserved (key_share)" }, /* https://tools.ietf.org/html/draft-ietf-tls-tls13-22 */
     { SSL_HND_HELLO_EXT_PRE_SHARED_KEY, "pre_shared_key" }, /* TLS 1.3 https://tools.ietf.org/html/draft-ietf-tls-tls13 */
     { SSL_HND_HELLO_EXT_EARLY_DATA, "early_data" }, /* TLS 1.3 https://tools.ietf.org/html/draft-ietf-tls-tls13 */
     { SSL_HND_HELLO_EXT_SUPPORTED_VERSIONS, "supported_versions" }, /* TLS 1.3 https://tools.ietf.org/html/draft-ietf-tls-tls13 */
@@ -1222,6 +1212,8 @@ const value_string tls_hello_extension_types[] = {
     { SSL_HND_HELLO_EXT_CERTIFICATE_AUTHORITIES, "certificate_authorities" }, /* https://tools.ietf.org/html/draft-ietf-tls-tls13-19#section-4.2.3.1 */
     { SSL_HND_HELLO_EXT_OID_FILTERS, "oid_filters" }, /* https://tools.ietf.org/html/draft-ietf-tls-tls13-19#section-4.3.2.1 */
     { SSL_HND_HELLO_EXT_POST_HANDSHAKE_AUTH, "post_handshake_auth" }, /* https://tools.ietf.org/html/draft-ietf-tls-tls13-20#section-4.2.5 */
+    { SSL_HND_HELLO_EXT_SIGNATURE_ALGORITHMS_CERT, "signature_algorithms_cert" }, /* https://tools.ietf.org/html/draft-ietf-tls-tls13-23 */
+    { SSL_HND_HELLO_EXT_KEY_SHARE, "key_share" }, /* https://tools.ietf.org/html/draft-ietf-tls-tls13-23 */
     { SSL_HND_HELLO_EXT_GREASE_0A0A, "Reserved (GREASE)" }, /* https://tools.ietf.org/html/draft-ietf-tls-grease */
     { SSL_HND_HELLO_EXT_GREASE_1A1A, "Reserved (GREASE)" }, /* https://tools.ietf.org/html/draft-ietf-tls-grease */
     { SSL_HND_HELLO_EXT_GREASE_2A2A, "Reserved (GREASE)" }, /* https://tools.ietf.org/html/draft-ietf-tls-grease */
@@ -1286,7 +1278,7 @@ const value_string tls_signature_algorithm[] = {
     { 0, NULL }
 };
 
-/* https://tools.ietf.org/html/draft-ietf-tls-tls13-21#section-4.2.3 */
+/* https://tools.ietf.org/html/draft-ietf-tls-tls13-23#section-4.2.3 */
 const value_string tls13_signature_algorithm[] = {
     { 0x0201, "rsa_pkcs1_sha1" },
     { 0x0203, "ecdsa_sha1" },
@@ -1296,11 +1288,14 @@ const value_string tls13_signature_algorithm[] = {
     { 0x0503, "ecdsa_secp384r1_sha384" },
     { 0x0601, "rsa_pkcs1_sha512" },
     { 0x0603, "ecdsa_secp521r1_sha512" },
-    { 0x0804, "rsa_pss_sha256" },
-    { 0x0805, "rsa_pss_sha384" },
-    { 0x0806, "rsa_pss_sha512" },
+    { 0x0804, "rsa_pss_rsae_sha256" },
+    { 0x0805, "rsa_pss_rsae_sha384" },
+    { 0x0806, "rsa_pss_rsae_sha512" },
     { 0x0807, "ed25519" },
     { 0x0808, "ed448" },
+    { 0x0809, "rsa_pss_pss_sha256" },
+    { 0x080a, "rsa_pss_pss_sha384" },
+    { 0x080b, "rsa_pss_pss_sha512" },
     { 0, NULL }
 };
 
@@ -1425,12 +1420,13 @@ static const ssl_alpn_protocol_t ssl_alpn_protocols[] = {
 const value_string quic_transport_parameter_id[] = {
     { SSL_HND_QUIC_TP_INITIAL_MAX_STREAM_DATA, "initial_max_stream_data" },
     { SSL_HND_QUIC_TP_INITIAL_MAX_DATA, "initial_max_data" },
-    { SSL_HND_QUIC_TP_INITIAL_MAX_STREAM_ID, "initial_max_stream_id" },
+    { SSL_HND_QUIC_TP_INITIAL_MAX_STREAM_ID_BIDI, "initial_max_stream_id_bidi" },
     { SSL_HND_QUIC_TP_IDLE_TIMEOUT, "idle_timeout" },
     { SSL_HND_QUIC_TP_OMIT_CONNECTION_ID, "omit_connection_id" },
     { SSL_HND_QUIC_TP_MAX_PACKET_SIZE, "max_packet_size" },
     { SSL_HND_QUIC_TP_STATELESS_RESET_TOKEN, "stateless_reset_token" },
     { SSL_HND_QUIC_TP_ACK_DELAY_EXPONENT, "ack_delay_exponent" },
+    { SSL_HND_QUIC_TP_INITIAL_MAX_STREAM_ID_UNI, "initial_max_stream_id_uni" },
     { 0, NULL }
 };
 
@@ -2748,75 +2744,72 @@ static gint tls12_handshake_hash(SslDecryptSession* ssl, gint md, StringInfo* ou
     return 0;
 }
 
+/**
+ * Obtains the label prefix used in HKDF-Expand-Label.  This function can be
+ * inlined and removed once support for draft 19 and before is dropped.
+ */
+static inline const char *
+tls13_hkdf_label_prefix(guint8 tls13_draft_version)
+{
+    if (tls13_draft_version && tls13_draft_version < 20) {
+        return "TLS 1.3, ";
+    } else {
+        return "tls13 ";
+    }
+}
+
+/*
+ * Computes HKDF-Expand-Label(Secret, Label, "", Length) with a custom label
+ * prefix.
+ */
 gboolean
-tls13_hkdf_expand_label(guchar draft_version,
-                        int md, const StringInfo *secret, const char *label, const char *hash_value,
+tls13_hkdf_expand_label(int md, const StringInfo *secret,
+                        const char *label_prefix, const char *label,
                         guint16 out_len, guchar **out)
 {
-    /* draft-ietf-tls-tls13-20:
-     * HKDF-Expand-Label(Secret, Label, HashValue, Length) =
+    /* draft-ietf-tls-tls13-23:
+     * HKDF-Expand-Label(Secret, Label, Context, Length) =
      *      HKDF-Expand(Secret, HkdfLabel, Length)
      * struct {
      *     uint16 length = Length;
-     *     opaque label<7..255> = "tls13 " + Label;
-     *     opaque hash_value<0..255> = HashValue;
+     *     opaque label<7..255> = "tls13 " + Label; // "tls13 " is label prefix.
+     *     opaque context<0..255> = Context;
      * } HkdfLabel;
      *
      * RFC 5869 HMAC-based Extract-and-Expand Key Derivation Function (HKDF):
      * HKDF-Expand(PRK, info, L) -> OKM
      */
-    guchar  lastoutput[DIGEST_MAX_SIZE];
-    gcry_md_hd_t h;
     gcry_error_t err;
+    const guint label_prefix_length = (guint) strlen(label_prefix);
     const guint label_length = (guint) strlen(label);
-    const guint hash_value_length = (guint) strlen(hash_value);
-    const guint hash_len = gcry_md_get_algo_dlen(md);
 
     /* Some sanity checks */
-    DISSECTOR_ASSERT(out_len > 0 && out_len <= 255 * hash_len);
-    DISSECTOR_ASSERT(label_length > 0 && label_length <= 255 - 6);
-    DISSECTOR_ASSERT(hash_value_length <= 255);
-    DISSECTOR_ASSERT(hash_len > 0 && hash_len <= DIGEST_MAX_SIZE);
-
-    err = gcry_md_open(&h, md, GCRY_MD_FLAG_HMAC);
-    if (err) {
-        ssl_debug_printf("%s failed to invoke hash func %d: %s\n", G_STRFUNC, md, gcry_strerror(err));
-        return FALSE;
-    }
+    DISSECTOR_ASSERT(label_length > 0 && label_prefix_length + label_length <= 255);
 
-    *out = (guchar *)wmem_alloc(NULL, out_len);
-
-    for (guint offset = 0; offset < out_len; offset += hash_len) {
-        gcry_md_reset(h);
-        gcry_md_setkey(h, secret->data, secret->data_len);  /* Set PRK */
+    /* info = HkdfLabel { length, label, context } */
+    GByteArray *info = g_byte_array_new();
+    const guint16 length = g_htons(out_len);
+    g_byte_array_append(info, (const guint8 *)&length, sizeof(length));
 
-        if (offset > 0) {
-            gcry_md_write(h, lastoutput, hash_len);         /* T(1..N) */
-        }
+    const guint8 label_vector_length = label_prefix_length + label_length;
+    g_byte_array_append(info, &label_vector_length, 1);
+    g_byte_array_append(info, label_prefix, label_prefix_length);
+    g_byte_array_append(info, label, label_length);
 
-        /* info = HkdfLabel { length, label, hash_value } */
-        gcry_md_putc(h, out_len >> 8);                      /* length */
-        gcry_md_putc(h, (guint8) out_len);
-        if (draft_version && draft_version < 20) {
-            /* Draft -19 and before use a different prefix.
-             * TODO remove this once implementations are updated for D20. */
-            gcry_md_putc(h, 9 + label_length);              /* label */
-            gcry_md_write(h, "TLS 1.3, ", 9);
-        } else {
-            gcry_md_putc(h, 6 + label_length);              /* label */
-            gcry_md_write(h, "tls13 ", 6);
-        }
-        gcry_md_write(h, label, label_length);
-        gcry_md_putc(h, hash_value_length);                 /* hash_value */
-        gcry_md_write(h, hash_value, hash_value_length);
+    const guint8 context_length = 0;
+    g_byte_array_append(info, &context_length, 1);
 
-        gcry_md_putc(h, (guint8) (offset / hash_len + 1));  /* constant 0x01..N */
+    *out = (guchar *)wmem_alloc(NULL, out_len);
+    err = hkdf_expand(md, secret->data, secret->data_len, info->data, info->len, *out, out_len);
+    g_byte_array_free(info, TRUE);
 
-        memcpy(lastoutput, gcry_md_read(h, md), hash_len);
-        memcpy(*out + offset, lastoutput, MIN(hash_len, out_len - offset));
+    if (err) {
+        ssl_debug_printf("%s failed  %d: %s\n", G_STRFUNC, md, gcry_strerror(err));
+        wmem_free(NULL, *out);
+        *out = NULL;
+        return FALSE;
     }
 
-    gcry_md_close(h);
     return TRUE;
 }
 /* HMAC and the Pseudorandom function }}} */
@@ -3015,7 +3008,7 @@ tls13_cipher_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _
 }
 
 tls13_cipher *
-tls13_cipher_create(guint8 tls13_draft_version, int cipher_algo, int cipher_mode, int hash_algo, StringInfo *secret, const gchar **error)
+tls13_cipher_create(const char *label_prefix, int cipher_algo, int cipher_mode, int hash_algo, const StringInfo *secret, const gchar **error)
 {
     tls13_cipher       *cipher = NULL;
     guchar             *write_key = NULL, *write_iv = NULL;
@@ -3030,11 +3023,11 @@ tls13_cipher_create(guint8 tls13_draft_version, int cipher_algo, int cipher_mode
     key_length = (guint) gcry_cipher_get_algo_keylen(cipher_algo);
     iv_length = TLS13_AEAD_NONCE_LENGTH;
 
-    if (!tls13_hkdf_expand_label(tls13_draft_version, hash_algo, secret, "key", "", key_length, &write_key)) {
+    if (!tls13_hkdf_expand_label(hash_algo, secret, label_prefix, "key", key_length, &write_key)) {
         *error = "Key expansion (key) failed";
         return NULL;
     }
-    if (!tls13_hkdf_expand_label(tls13_draft_version, hash_algo, secret, "iv", "", iv_length, &write_iv)) {
+    if (!tls13_hkdf_expand_label(hash_algo, secret, label_prefix, "iv", iv_length, &write_iv)) {
         *error = "Key expansion (IV) failed";
         goto end;
     }
@@ -3537,7 +3530,7 @@ fail:
 }
 
 /* Generated the key material based on the given secret. */
-static gboolean
+gboolean
 tls13_generate_keys(SslDecryptSession *ssl_session, const StringInfo *secret, gboolean is_from_server)
 {
     gboolean    success = FALSE;
@@ -3585,11 +3578,12 @@ tls13_generate_keys(SslDecryptSession *ssl_session, const StringInfo *secret, gb
     iv_length = 12;
     ssl_debug_printf("%s key_length %u iv_length %u\n", G_STRFUNC, key_length, iv_length);
 
-    if (!tls13_hkdf_expand_label(ssl_session->session.tls13_draft_version, hash_algo, secret, "key", "", key_length, &write_key)) {
+    const char *label_prefix = tls13_hkdf_label_prefix(ssl_session->session.tls13_draft_version);
+    if (!tls13_hkdf_expand_label(hash_algo, secret, label_prefix, "key", key_length, &write_key)) {
         ssl_debug_printf("%s write_key expansion failed\n", G_STRFUNC);
         return FALSE;
     }
-    if (!tls13_hkdf_expand_label(ssl_session->session.tls13_draft_version, hash_algo, secret, "iv", "", iv_length, &write_iv)) {
+    if (!tls13_hkdf_expand_label(hash_algo, secret, label_prefix, "iv", iv_length, &write_iv)) {
         ssl_debug_printf("%s write_iv expansion failed\n", G_STRFUNC);
         goto end;
     }
@@ -4946,23 +4940,23 @@ ssl_finalize_decryption(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map)
     }
 } /* }}} */
 
-/* Load the new key. */
-void
-tls13_change_key(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map,
-                 gboolean is_from_server, TLSRecordType type)
+/* Load the traffic key secret from the keylog file. */
+StringInfo *
+tls13_load_secret(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map,
+                  gboolean is_from_server, TLSRecordType type)
 {
     GHashTable *key_map;
     const char *label;
 
     if (ssl->session.version != TLSV1DOT3_VERSION) {
         ssl_debug_printf("%s TLS version %#x is not 1.3\n", G_STRFUNC, ssl->session.version);
-        return;
+        return NULL;
     }
 
     if (ssl->client_random.data_len == 0) {
         /* May happen if Hello message is missing and Finished is found. */
         ssl_debug_printf("%s missing Client Random\n", G_STRFUNC);
-        return;
+        return NULL;
     }
 
     switch (type) {
@@ -5006,13 +5000,26 @@ tls13_change_key(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map,
         } else {
             ssl->client = NULL;
         }
-        return;
+        return NULL;
     }
 
     /* TLS 1.3 secret found, set new keys. */
     ssl_debug_printf("%s Retrieved TLS 1.3 traffic secret.\n", G_STRFUNC);
     ssl_print_string("Client Random", &ssl->client_random);
     ssl_print_string(label, secret);
+    return secret;
+}
+
+/* Load the new key. */
+void
+tls13_change_key(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map,
+                 gboolean is_from_server, TLSRecordType type)
+{
+    StringInfo *secret = tls13_load_secret(ssl, mk_map, is_from_server, type);
+    if (!secret) {
+        return;
+    }
+
     if (tls13_generate_keys(ssl, secret, is_from_server)) {
         /*
          * Remember the application traffic secret to support Key Update. The
@@ -5064,8 +5071,9 @@ tls13_key_update(SslDecryptSession *ssl, gboolean is_from_server)
     int hash_algo = ssl_get_digest_by_name(hash_name);
     const guint hash_len = app_secret->data_len;
     guchar *new_secret;
-    if (!tls13_hkdf_expand_label(ssl->session.tls13_draft_version,
-                                 hash_algo, app_secret, "application traffic secret", "",
+    if (!tls13_hkdf_expand_label(hash_algo, app_secret,
+                                 tls13_hkdf_label_prefix(ssl->session.tls13_draft_version),
+                                 "application traffic secret",
                                  hash_len, &new_secret)) {
         ssl_debug_printf("%s traffic_secret_N+1 expansion failed\n", G_STRFUNC);
         return;
@@ -6451,7 +6459,7 @@ ssl_dissect_hnd_hello_ext_quic_transport_parameters(ssl_common_dissect_t *hf, tv
                                                     proto_tree *tree, guint32 offset, guint32 offset_end,
                                                     guint8 hnd_type, SslDecryptSession *ssl _U_)
 {
-    guint32 quic_length, parameter_length, supported_versions_length, next_offset, version;
+    guint32 quic_length, parameter_length, supported_versions_length, next_offset;
 
     /* https://tools.ietf.org/html/draft-ietf-quic-transport-08#section-7.4
      *  uint32 QuicVersion;
@@ -6482,28 +6490,19 @@ ssl_dissect_hnd_hello_ext_quic_transport_parameters(ssl_common_dissect_t *hf, tv
      *              QuicVersion negotiated_version;
      *              QuicVersion supported_versions<4..2^8-4>;
      *      };
-     *      TransportParameter parameters<30..2^16-1>;
+     *      TransportParameter parameters<22..2^16-1>;
      *  } TransportParameters;
      */
     switch (hnd_type) {
     case SSL_HND_CLIENT_HELLO:
-        version = tvb_get_ntohl(tvb, offset);
-        if(version <= 0xff000007){ /* No longer negotiated_version on Client Hello with >= draft-07 */
-            proto_tree_add_item(tree, hf->hf.hs_ext_quictp_negotiated_version,
-                                tvb, offset, 4, ENC_BIG_ENDIAN);
-            offset += 4;
-        }
         proto_tree_add_item(tree, hf->hf.hs_ext_quictp_initial_version,
                             tvb, offset, 4, ENC_BIG_ENDIAN);
         offset += 4;
         break;
     case SSL_HND_ENCRYPTED_EXTENSIONS:
-        version = tvb_get_ntohl(tvb, offset);
-        if(version > 0xff000007){ /* Now negotiated_version on Encrypted Extensions (>= draft-08) */
-            proto_tree_add_item(tree, hf->hf.hs_ext_quictp_negotiated_version,
-                                tvb, offset, 4, ENC_BIG_ENDIAN);
-            offset += 4;
-        }
+        proto_tree_add_item(tree, hf->hf.hs_ext_quictp_negotiated_version,
+                            tvb, offset, 4, ENC_BIG_ENDIAN);
+        offset += 4;
         /* QuicVersion supported_versions<4..2^8-4>;*/
         if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &supported_versions_length,
                             hf->hf.hs_ext_quictp_supported_versions_len, 4, G_MAXUINT8-3)) {
@@ -6524,9 +6523,9 @@ ssl_dissect_hnd_hello_ext_quic_transport_parameters(ssl_common_dissect_t *hf, tv
         return offset;
     }
 
-    /* TransportParameter parameters<30..2^16-1>; */
+    /* TransportParameter parameters<22..2^16-1>; */
     if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &quic_length,
-                        hf->hf.hs_ext_quictp_len, 30, G_MAXUINT16)) {
+                        hf->hf.hs_ext_quictp_len, 22, G_MAXUINT16)) {
         return offset_end;
     }
     offset += 2;
@@ -6569,8 +6568,8 @@ ssl_dissect_hnd_hello_ext_quic_transport_parameters(ssl_common_dissect_t *hf, tv
                 proto_item_append_text(parameter_tree, " %u", tvb_get_ntohl(tvb, offset));
                 offset += 4;
             break;
-            case SSL_HND_QUIC_TP_INITIAL_MAX_STREAM_ID:
-                proto_tree_add_item(parameter_tree, hf->hf.hs_ext_quictp_parameter_initial_max_stream_id,
+            case SSL_HND_QUIC_TP_INITIAL_MAX_STREAM_ID_BIDI:
+                proto_tree_add_item(parameter_tree, hf->hf.hs_ext_quictp_parameter_initial_max_stream_id_bidi,
                                     tvb, offset, 4, ENC_BIG_ENDIAN);
                 proto_item_append_text(parameter_tree, " %u", tvb_get_ntohl(tvb, offset));
                 offset += 4;
@@ -6602,6 +6601,12 @@ ssl_dissect_hnd_hello_ext_quic_transport_parameters(ssl_common_dissect_t *hf, tv
                 /*TODO display multiplier (x8) and expert info about invaluid value (> 20) ? */
                 offset += 1;
             break;
+            case SSL_HND_QUIC_TP_INITIAL_MAX_STREAM_ID_UNI:
+                proto_tree_add_item(parameter_tree, hf->hf.hs_ext_quictp_parameter_initial_max_stream_id_uni,
+                                    tvb, offset, 4, ENC_BIG_ENDIAN);
+                proto_item_append_text(parameter_tree, " %u", tvb_get_ntohl(tvb, offset));
+                offset += 4;
+            break;
             default:
                 offset += parameter_length;
                 /*TODO display expert info about unknown ? */
@@ -7465,19 +7470,26 @@ ssl_dissect_hnd_new_ses_ticket(ssl_common_dissect_t *hf, tvbuff_t *tvb, packet_i
      *  } NewSessionTicket;
      */
     proto_tree *subtree;
+    proto_item *subitem;
     guint32     ticket_len;
     gboolean    is_tls13 = session->version == TLSV1DOT3_VERSION;
     guchar      draft_version = session->tls13_draft_version;
+    guint32     lifetime_hint;
 
     subtree = proto_tree_add_subtree(tree, tvb, offset, offset_end - offset,
                                      hf->ett.session_ticket, NULL,
                                      "TLS Session Ticket");
 
     /* ticket lifetime hint */
-    proto_tree_add_item(subtree, hf->hf.hs_session_ticket_lifetime_hint,
-                        tvb, offset, 4, ENC_BIG_ENDIAN);
+    subitem = proto_tree_add_item_ret_uint(subtree, hf->hf.hs_session_ticket_lifetime_hint,
+                                           tvb, offset, 4, ENC_BIG_ENDIAN, &lifetime_hint);
     offset += 4;
 
+    if (lifetime_hint >= 60) {
+        gchar *time_str = unsigned_time_secs_to_str(wmem_packet_scope(), lifetime_hint);
+        proto_item_append_text(subitem, " (%s)", time_str);
+    }
+
     if (is_tls13) {
 
         /* for TLS 1.3: ticket_age_add */
@@ -8055,6 +8067,7 @@ ssl_dissect_hnd_extension(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *t
             offset = ssl_dissect_hnd_hello_ext_ec_point_formats(hf, tvb, ext_tree, offset);
             break;
         case SSL_HND_HELLO_EXT_SIGNATURE_ALGORITHMS:
+        case SSL_HND_HELLO_EXT_SIGNATURE_ALGORITHMS_CERT: /* since TLS 1.3 draft -23 */
             offset = ssl_dissect_hnd_hello_ext_sig_hash_algs(hf, tvb, ext_tree, pinfo, offset, next_offset);
             break;
         case SSL_HND_HELLO_EXT_USE_SRTP:
@@ -8118,6 +8131,7 @@ ssl_dissect_hnd_extension(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *t
         case SSL_HND_HELLO_EXT_SESSION_TICKET_TLS:
             offset = ssl_dissect_hnd_hello_ext_session_ticket(hf, tvb, ext_tree, offset, next_offset, hnd_type, ssl);
             break;
+        case SSL_HND_HELLO_EXT_KEY_SHARE_OLD: /* used before TLS 1.3 draft -23 */
         case SSL_HND_HELLO_EXT_KEY_SHARE:
             offset = ssl_dissect_hnd_hello_ext_key_share(hf, tvb, pinfo, ext_tree, offset, next_offset, hnd_type);
             break;