Module Tls.Engine

Transport layer security

TLS is an implementation of transport layer security in OCaml. TLS is a widely used security protocol which establishes an end-to-end secure channel (with optional (mutual) authentication) between two endpoints. It uses TCP/IP as transport. This library supports all four versions of TLS: 1.3, RFC8446, 1.2, RFC5246, 1.1, RFC4346, and 1.0, RFC2246. SSL, the previous protocol definition, is not supported.

TLS is algorithmically agile: protocol version, key exchange algorithm, symmetric cipher, and message authentication code are negotiated upon connection.

This library implements several extensions of TLS, AES ciphers, TLS extensions (such as server name indication, SNI), Renegotiation extension, Session Hash and Extended Master Secret Extension.

This library does not contain insecure cipher suites (such as single DES, export ciphers, ...). It does not expose the server time in the server random, requires secure renegotiation.

This library consists of a core, implemented in a purely functional matter (Engine, this module), and effectful parts: Tls_lwt and Tls_mirage.

v1.0.4

Abstract state type

type state

The abstract type of a TLS state.

Constructors

val client : Config.client -> state * string

client client is tls * out where tls is the initial state, and out the initial client hello

val server : Config.server -> state

server server is tls where tls is the initial server state

Protocol failures

type error = [
  1. | `AuthenticationFailure of X509.Validation.validation_error
  2. | `NoConfiguredCiphersuite of Ciphersuite.ciphersuite list
  3. | `NoConfiguredVersions of Core.tls_version list
  4. | `NoConfiguredSignatureAlgorithm of Core.signature_algorithm list
  5. | `NoMatchingCertificateFound of string
  6. | `CouldntSelectCertificate
]

failures which can be mitigated by reconfiguration

type fatal = [
  1. | `Protocol_version of [ `None_supported of Core.tls_any_version list | `Unknown_record of int * int | `Bad_record of Core.tls_any_version ]
  2. | `Unexpected of [ `Content_type of int | `Message of string | `Handshake of Core.tls_handshake ]
  3. | `Decode of string
  4. | `Handshake of [ `Message of string | `Fragments | `BadDH of string | `BadECDH of Mirage_crypto_ec.error ]
  5. | `Bad_certificate of string
  6. | `Missing_extension of string
  7. | `Bad_mac
  8. | `Record_overflow of int
  9. | `Unsupported_extension
  10. | `Inappropriate_fallback
  11. | `No_application_protocol
]

failures from received garbage or lack of features

type failure = [
  1. | `Error of error
  2. | `Fatal of fatal
  3. | `Alert of Packet.alert_type
]

type of failures

val alert_of_failure : failure -> Packet.alert_level * Packet.alert_type

alert_of_failure failure is alert, the TLS alert type for this failure.

val string_of_failure : failure -> string

string_of_failure failure is string, the string representation of the failure.

val pp_failure : failure Fmt.t

pp_failure failure pretty-prints failure.

Protocol handling

type ret = (state * [ `Eof ] option * [ `Response of string option ] * [ `Data of string option ], failure * [ `Response of string ]) Stdlib.result

result type of handle_tls: either failed to handle the incoming buffer (`Fail) with failure and potentially a message to send to the other endpoint, or sucessful operation (`Ok) with a new state, an end of file (`Eof), or an incoming (`Alert). Possibly some `Response to the other endpoint is needed, and potentially some `Data for the application was received.

val handle_tls : state -> string -> ret

handle_tls state buffer is ret, depending on incoming state and buffer, the result is the appropriate ret

val handshake_in_progress : state -> bool

handshake_in_progrss state is a predicate which indicates whether there is a handshake in progress or scheduled.

val send_application_data : state -> string list -> (state * string) option

send_application_data tls outs is Some (tls', out) where tls' is the new tls state, and out the cstruct to send over the wire (encrypted outs) when the TLS session is ready. When the TLS session is not ready it is None.

val send_close_notify : state -> state * string

send_close_notify tls is tls' * out where tls' is the new tls state, and out the (possible encrypted) close notify alert.

val reneg : ?authenticator:X509.Authenticator.t -> ?acceptable_cas:X509.Distinguished_name.t list -> ?cert:Config.own_cert -> state -> (state * string) option

reneg ~authenticator ~acceptable_cas ~cert tls initiates a renegotation on tls, using the provided authenticator. It is tls' * out where tls' is the new tls state, and out either a client hello or hello request (depending on which communication endpoint tls is).

val key_update : ?request:bool -> state -> (state * string, failure) Stdlib.result

key_update ~request state initiates a KeyUpdate (TLS 1.3 only). If request is provided and true (the default), the KeyUpdate message contains a request that the peer should update their traffic key as well.

Session information

val epoch : state -> (Core.epoch_data, unit) Stdlib.result

epoch state is epoch, which contains the session information. If there's no established session yet, an error is returned.

val export_key_material : Core.epoch_data -> ?context:string -> string -> int -> string

export_key_material epoch_data ?context label length is the RFC 5705 exported key material of length bytes using label and, if provided, context.

val channel_binding : Core.epoch_data -> [ `Tls_exporter | `Tls_unique | `Tls_server_endpoint ] -> (string, [ `Msg of string ]) Stdlib.result

channel_binding epoch_data mode is the RFC 5929 and RFC 9266 specified channel binding. Please note that `Tls_unique will error for TLS 1.3 sessions, and `Tls_exporter is not recommended for TLS < 1.3 sessions (unless the uniqueness is ensured via another path).