* 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"
{ 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" },
{ 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 */
{ 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 */
{ 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" },
{ 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 }
};
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 }
};
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 }}} */
}
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;
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;
}
}
/* 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;
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;
}
}
} /* }}} */
-/* 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) {
} 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
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;
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;
* 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)) {
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;
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;
/*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 ? */
* } 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 */
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:
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;