[][src]Crate tls_parser

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.

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

extern crate nom;
extern crate tls_parser;

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

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 extern crate rusticata_macros;

Structs

CertificateStatusType
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 if 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 curves, as defined in RFC4492, RFC7027, RFC7919 and IANA Supported Groups Registry

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

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

TlsState

TLS machine possible states

Constants

MAX_RECORD_LEN

Max record size (RFC8446 5.1)

Statics

CIPHERS

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_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_raw_record

Parse DTLS record, leaving fragment unparsed

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_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 This function is deprecated. Use parse_tls_plaintext instead.

tls_parser_many

Parse one chunk of data, possibly containing multiple TLS plaintext records This function is deprecated. Use parse_tls_plaintext instead, checking if there are remaining bytes, and calling parse_tls_plaintext recursively.

tls_state_transition

Update the TLS state machine, doing one transition

Type Definitions

IResult

Holds the result of parsing functions