Expand description
§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 plaintextparse_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§
- Certificate
Status Type - Cipher
Suite NotFound - 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
- DTLS
Client Hello - DTLS
Hello Verify Request - DTLS
Message Handshake - DTLS Generic handshake message
- DTLS
Plaintext - DTLS Plaintext record
- DTLS
RawRecord - DTLS
Record Header - DTLS Plaintext record header
- Digitally
Signed - 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
- ECCurve
Type - 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
- Explicit
Prime Content - Elliptic curve parameters, conveyed verbosely as a prime field, as defined in RFC4492 section 5.4
- Hash
Algorithm - Hash algorithms, as defined in [RFC5246]
- KeyShare
Entry - KeyUpdate
Request - Key update request (TLS 1.3)
- Named
Group - Named elliptic curves
- OidFilter
- PskKey
Exchange Mode - RawCertificate
- A raw certificate, which should be a DER-encoded X.509 certificate.
- SNIType
- ServerDH
Params - Diffie-Hellman parameters, defined in [RFC5246] section 7.4.3
- ServerECDH
Params - ECDH parameters defined in RFC4492 section 5.4
- Sign
Algorithm - Signature algorithms, as defined in [RFC5246]
- Signature
AndHash Algorithm - Signature
Scheme - Signature algorithms, as defined in [RFC8446] 4.2.3
- Signed
Certificate Timestamp - Signed Certificate Timestamp as defined in RFC6962 Section 3.2
- TlsAlert
Description - TLS alert description
- TlsAlert
Severity - TLS alert severity
- TlsCertificate
Contents - The certificate chain, usually composed of the certificate, and all required certificate authorities.
- TlsCertificate
Request Contents - Certificate request, as defined in RFC5246 section 7.4.4
- TlsCertificate
Status Contents - Certificate status response, as defined in RFC6066 section 8
- TlsCipher
Suite - TLS Ciphersuite
- TlsCipher
SuiteID - TlsClient
Hello Contents - TLS Client Hello (from TLS 1.0 to TLS 1.2)
- TlsCompressionID
- TlsEncrypted
- Encrypted TLS record (containing opaque data)
- TlsEncrypted
Content - TLS encrypted data
- TlsExtension
Type - TLS extension types, defined in the IANA Transport Layer Security (TLS) Extensions registry
- TlsHandshake
Type - Handshake type
- TlsHeartbeat
Message Type - Heartbeat type, as defined in RFC6520 section 3
- TlsHello
Retry Request Contents - TLS Hello Retry Request (TLS 1.3)
- TlsMessage
Alert - TLS alert message
- TlsMessage
Application Data - TLS application data
- TlsMessage
Heartbeat - TLS heartbeat message, as defined in RFC6520
- TlsNew
Session Ticket Content - Session ticket, as defined in RFC5077
- TlsNext
Protocol Content - Next protocol response, defined in draft-agl-tls-nextprotoneg-03
- TlsPlaintext
- TLS plaintext record
- TlsRaw
Record - Tls Record with raw (unparsed) data
- TlsRecord
Header - TLS record header
- TlsRecord
Type - Content type, as defined in IANA TLS ContentType registry
- TlsServer
Hello Contents - TLS Server Hello (from TLS 1.0 to TLS 1.2)
- TlsServer
Hello V13Draft18 Contents - TLS Server Hello (TLS 1.3 draft 18)
- TlsServer
KeyExchange Contents - Server key exchange parameters
- TlsVersion
- TLS version
Enums§
- DTLS
Message - DTLS plaintext message
- DTLS
Message Handshake Body - DTLS Generic handshake message
- ECParameters
Content - Elliptic curve parameters content (depending on EC type)
- Err
- The
Err
enum indicates the parser was not successful - State
Change Error - Error types for the state machine
- TlsCipher
Au - Authentication methods
- TlsCipher
Enc - Encryption methods
- TlsCipher
EncMode - Encryption modes
- TlsCipher
Kx - Key exchange methods
- TlsCipher
Mac - Message Authentication Code (MAC) methods
- TlsClient
KeyExchange Contents - Client key exchange parameters
- TlsExtension
- TLS extensions
- TlsMessage
- TLS plaintext message
- TlsMessage
Handshake - 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§
Traits§
- Client
Hello - 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 thesignature_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_
parser Deprecated - 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