Crate tls_parser

Source
Expand description

License: MIT Apache License 2.0 Crates.io Version GitHub CI Minimum rustc version

§TLS Parser

A TLS parser, implemented with the nom parser combinator framework.

The goal of this parser is to implement TLS messages analysis, for example to use rules from a network IDS, for ex during the TLS handshake.

It implements structures and parsing functions for records and messages, but need additional code to handle fragmentation, or to fully inspect messages. Parsing some TLS messages requires to know the previously selected parameters. See the rusticata TLS parser for a full example.

It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken to ensure security and safety of this crate, including design (recursion limit, defensive programming), tests, and fuzzing. It also aims to be panic-free.

The code is available on Github and is part of the Rusticata project.

§Parsing records

The main parsing functions are located in the tls.rs file. The entry functions are:

  • parse_tls_plaintext: parses a record as plaintext
  • parse_tls_encrypted: read an encrypted record. The parser has no crypto or decryption features, so the content will be left as opaque data.

§Examples

use tls_parser::parse_tls_plaintext;
use tls_parser::nom::{Err, IResult};

let bytes : &[u8]= include_bytes!("../assets/client_hello_dhe.bin");
// [ 0x16, 0x03, 0x01 ... ];
let res = parse_tls_plaintext(&bytes);
match res {
    Ok((rem,record)) => {
        // rem is the remaining data (not parsed)
        // record is an object of type TlsRecord
    },
    Err(Err::Incomplete(needed)) => {
        eprintln!("Defragmentation required (TLS record)");
    },
    Err(e) => { eprintln!("parse_tls_record_with_header failed: {:?}",e); }
}

Note that knowing if a record is plaintext or not is the responsibility of the caller.

As reading TLS records may imply defragmenting records, some functions are provided to only read the record as opaque data (which ensures the record is complete and gives the record header) and then reading messages from data.

Here is an example of two-steps parsing:


// [ 0x16, 0x03, 0x01 ... ];
match parse_tls_raw_record(bytes) {
    Ok((rem, ref r)) => {
        match parse_tls_record_with_header(r.data, &r.hdr) {
            Ok((rem2,ref msg_list)) => {
                for msg in msg_list {
                    // msg has type TlsMessage
                }
            }
            Err(Err::Incomplete(needed)) => { eprintln!("incomplete record") }
            Err(_) => { eprintln!("error while parsing record") }
        }
    }
    Err(Err::Incomplete(needed)) => { eprintln!("incomplete record header") }
    Err(_) => { eprintln!("error while parsing record header") }
}

Some additional work is required if reading packets from the network, to support reassembly of TCP segments and reassembly of TLS records.

For a complete example of a TLS parser supporting defragmentation and states, see the rusticata/src/tls.rs file of the rusticata crate.

§State machine

A TLS state machine is provided in tls_states.rs. The state machine is separated from the parsing functions, and is almost independent. It is implemented as a table of transitions, mainly for the handshake phase.

After reading a TLS message using the previous functions, the TLS state can be updated using the tls_state_transition function. If the transition succeeds, it returns Ok(new_state), otherwise it returns Err(error_state).


struct ParseContext {
    state: TlsState,
}

match tls_state_transition(ctx.state, msg, to_server) {
    Ok(s)  => { ctx.state = s; Ok(()) }
    Err(_) => {
        ctx.state = TlsState::Invalid;
        Err("Invalid state")
    }
}

§Implementation notes

When parsing messages, if a field is an integer corresponding to an enum of known values, it is not parsed as an enum type, but as an integer. While this complicates accesses, it allows to read invalid values and continue parsing (for an IDS, it’s better to read values than to get a generic parse error).

Re-exports§

pub use nom;
pub use rusticata_macros;

Structs§

CertificateStatusType
CipherSuiteNotFound
CtExtensions
CtExtensions as defined in RFC6962 Section 3.2
CtLogID
LogID as defined in RFC6962 Section 3.2
CtVersion
Certificate Transparency Version as defined in RFC6962 Section 3.2
DTLSClientHello
DTLSHelloVerifyRequest
DTLSMessageHandshake
DTLS Generic handshake message
DTLSPlaintext
DTLS Plaintext record
DTLSRawRecord
DTLSRecordHeader
DTLS Plaintext record header
DigitallySigned
DigitallySigned structure from [RFC2246] section 4.7 has no algorithm definition. This should be deprecated in favor of DigitallySigned structure from [RFC5246] section 4.7
ECCurve
Elliptic curve
ECCurveType
Elliptic curve types, as defined in the IANA EC Curve Type Registry Registry
ECParameters
Elliptic curve parameters, defined in RFC4492 section 5.4
ECPoint
EC Point
ExplicitPrimeContent
Elliptic curve parameters, conveyed verbosely as a prime field, as defined in RFC4492 section 5.4
HashAlgorithm
Hash algorithms, as defined in [RFC5246]
KeyShareEntry
KeyUpdateRequest
Key update request (TLS 1.3)
NamedGroup
Named elliptic curves
OidFilter
PskKeyExchangeMode
RawCertificate
A raw certificate, which should be a DER-encoded X.509 certificate.
SNIType
ServerDHParams
Diffie-Hellman parameters, defined in [RFC5246] section 7.4.3
ServerECDHParams
ECDH parameters defined in RFC4492 section 5.4
SignAlgorithm
Signature algorithms, as defined in [RFC5246]
SignatureAndHashAlgorithm
SignatureScheme
Signature algorithms, as defined in [RFC8446] 4.2.3
SignedCertificateTimestamp
Signed Certificate Timestamp as defined in RFC6962 Section 3.2
TlsAlertDescription
TLS alert description
TlsAlertSeverity
TLS alert severity
TlsCertificateContents
The certificate chain, usually composed of the certificate, and all required certificate authorities.
TlsCertificateRequestContents
Certificate request, as defined in RFC5246 section 7.4.4
TlsCertificateStatusContents
Certificate status response, as defined in RFC6066 section 8
TlsCipherSuite
TLS Ciphersuite
TlsCipherSuiteID
TlsClientHelloContents
TLS Client Hello (from TLS 1.0 to TLS 1.2)
TlsCompressionID
TlsEncrypted
Encrypted TLS record (containing opaque data)
TlsEncryptedContent
TLS encrypted data
TlsExtensionType
TLS extension types, defined in the IANA Transport Layer Security (TLS) Extensions registry
TlsHandshakeType
Handshake type
TlsHeartbeatMessageType
Heartbeat type, as defined in RFC6520 section 3
TlsHelloRetryRequestContents
TLS Hello Retry Request (TLS 1.3)
TlsMessageAlert
TLS alert message
TlsMessageApplicationData
TLS application data
TlsMessageHeartbeat
TLS heartbeat message, as defined in RFC6520
TlsNewSessionTicketContent
Session ticket, as defined in RFC5077
TlsNextProtocolContent
Next protocol response, defined in draft-agl-tls-nextprotoneg-03
TlsPlaintext
TLS plaintext record
TlsRawRecord
Tls Record with raw (unparsed) data
TlsRecordHeader
TLS record header
TlsRecordType
Content type, as defined in IANA TLS ContentType registry
TlsServerHelloContents
TLS Server Hello (from TLS 1.0 to TLS 1.2)
TlsServerHelloV13Draft18Contents
TLS Server Hello (TLS 1.3 draft 18)
TlsServerKeyExchangeContents
Server key exchange parameters
TlsVersion
TLS version

Enums§

DTLSMessage
DTLS plaintext message
DTLSMessageHandshakeBody
DTLS Generic handshake message
ECParametersContent
Elliptic curve parameters content (depending on EC type)
Err
The Err enum indicates the parser was not successful
StateChangeError
Error types for the state machine
TlsCipherAu
Authentication methods
TlsCipherEnc
Encryption methods
TlsCipherEncMode
Encryption modes
TlsCipherKx
Key exchange methods
TlsCipherMac
Message Authentication Code (MAC) methods
TlsClientKeyExchangeContents
Client key exchange parameters
TlsExtension
TLS extensions
TlsMessage
TLS plaintext message
TlsMessageHandshake
Generic handshake message
TlsPRF
Pseudo-Random Function (PRF) Function
TlsState
TLS machine possible states

Constants§

MAX_RECORD_LEN
Max record size for TLSCipherText (RFC8446 5.2)

Statics§

CIPHERS

Traits§

ClientHello
A trait that both TLS & DTLS satisfy

Functions§

parse_content_and_signature
Parse DigitallySigned object, depending on the ext parameter which should be true if the TLS client has sent the signature_algorithms extension
parse_ct_signed_certificate_timestamp
Parses as single Signed Certificate Timestamp entry
parse_ct_signed_certificate_timestamp_list
Parses a list of Signed Certificate Timestamp entries
parse_dh_params
parse_digitally_signed
parse_digitally_signed_old
parse_dtls_message_alert
Parse a DTLS alert message
parse_dtls_message_changecipherspec
Parse a DTLS changecipherspec message
parse_dtls_message_handshake
Parse a DTLS handshake message
parse_dtls_plaintext_record
Parse one DTLS plaintext record
parse_dtls_plaintext_records
Parse multiple DTLS plaintext record
parse_dtls_record_header
DTLS record header
parse_dtls_record_with_header
parse_ec_parameters
parse_ecdh_params
parse_named_groups
Parse the entire input as a list of named groups (curves)
parse_tls_client_hello_extension
Parse a single TLS Client Hello extension
parse_tls_client_hello_extensions
Parse zero or more TLS Client Hello extensions
parse_tls_encrypted
Parse one packet only, as encrypted content
parse_tls_extension
Parse a single TLS extension (of any type)
parse_tls_extension_alpn_content
Defined in [RFC7301]
parse_tls_extension_cookie
parse_tls_extension_early_data
parse_tls_extension_ec_point_formats
parse_tls_extension_ec_point_formats_content
parse_tls_extension_elliptic_curves
parse_tls_extension_elliptic_curves_content
parse_tls_extension_encrypt_then_mac
Encrypt-then-MAC is defined in [RFC7366]
parse_tls_extension_encrypted_server_name
Encrypted Server Name, defined in [draft-ietf-tls-esni]
parse_tls_extension_extended_master_secret
Extended Master Secret is defined in [RFC7627]
parse_tls_extension_heartbeat
parse_tls_extension_heartbeat_content
parse_tls_extension_key_share
parse_tls_extension_max_fragment_length
Max fragment length [RFC6066]
parse_tls_extension_max_fragment_length_content
Max fragment length [RFC6066]
parse_tls_extension_pre_shared_key
parse_tls_extension_psk_key_exchange_modes
parse_tls_extension_psk_key_exchange_modes_content
parse_tls_extension_renegotiation_info_content
Renegotiation Info, defined in [RFC5746]
parse_tls_extension_session_ticket
parse_tls_extension_signature_algorithms
parse_tls_extension_signature_algorithms_content
Parse ‘Signature Algorithms’ extension (rfc8446, TLS 1.3 only)
parse_tls_extension_signed_certificate_timestamp_content
Defined in [RFC6962]
parse_tls_extension_sni
parse_tls_extension_sni_content
parse_tls_extension_sni_hostname
parse_tls_extension_status_request
parse_tls_extension_supported_versions
parse_tls_extension_unknown
parse_tls_extensions
Parse zero or more TLS extensions (of any type)
parse_tls_handshake_certificaterequest
Parse a CertificateRequest handshake message
parse_tls_handshake_certificatestatus
Parse handshake message contents for CertificateStatus ([RFC6066])
parse_tls_handshake_client_hello
Parse handshake message contents for ClientHello
parse_tls_handshake_msg_certificate
Parse a Certificate handshake message
parse_tls_handshake_msg_certificaterequest
Parse a CertificateRequest handshake message
parse_tls_handshake_msg_certificatestatus
Parse a CertificateStatus handshake message ([RFC6066])
parse_tls_handshake_msg_certificateverify
Parse a CertificateVerify handshake message
parse_tls_handshake_msg_client_hello
Parse a ClientHello handshake message
parse_tls_handshake_msg_clientkeyexchange
Parse a ClientKeyExchange handshake message
parse_tls_handshake_msg_finished
Parse a Finished handshake message
parse_tls_handshake_msg_hello_request
Parse a HelloRequest handshake message
parse_tls_handshake_msg_hello_retry_request
Parse a HelloRetryRequest handshake message
parse_tls_handshake_msg_key_update
Parse a KeyUpdate handshake message
parse_tls_handshake_msg_newsessionticket
Parse a NewSessionTicket handshake message
parse_tls_handshake_msg_next_protocol
Parse a NextProtocol handshake message
parse_tls_handshake_msg_server_hello
Parse a ServerHello handshake message (all TLS versions)
parse_tls_handshake_msg_serverdone
Parse a ServerDone handshake message
parse_tls_handshake_msg_serverkeyexchange
Parse a ServerKeyExchange handshake message
parse_tls_handshake_next_protocol
Parse handshake message contents for NextProtocol
parse_tls_handshake_server_hello
Parse handshake message contents for ServerHello (all TLS versions except 1.3 draft 18)
parse_tls_message_alert
Parse a TLS alert message
parse_tls_message_applicationdata
Parse a TLS applicationdata message
parse_tls_message_changecipherspec
Parse a TLS changecipherspec message
parse_tls_message_handshake
Parse a TLS handshake message
parse_tls_message_heartbeat
Parse a TLS heartbeat message
parse_tls_plaintext
Parse one packet only, as plaintext A single record can contain multiple messages, they must share the same record type
parse_tls_raw_record
Read TLS record envelope, but do not decode data
parse_tls_record_header
Read TLS record header
parse_tls_record_with_header
Given data and a TLS record header, parse content.
parse_tls_server_hello_extension
Parse a single TLS Server Hello extension
parse_tls_server_hello_extensions
Parse zero or more TLS Server Hello extensions
tls_parserDeprecated
Parse one packet only, as plaintext
tls_parser_many
Parse one chunk of data, possibly containing multiple TLS plaintext records
tls_state_transition
Update the TLS state machine, doing one transition

Type Aliases§

IResult
Holds the result of parsing functions