Skip to content

Commit

Permalink
Merge pull request #262 from mirleft/documentation
Browse files Browse the repository at this point in the history
Documentation
  • Loading branch information
hannesm committed Mar 19, 2015
2 parents ec9a6a4 + 77dbd2b commit 31a7e6a
Show file tree
Hide file tree
Showing 17 changed files with 274 additions and 94 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[![Build Status](https://travis-ci.org/mirleft/ocaml-tls.svg?branch=master)](https://travis-ci.org/mirleft/ocaml-tls)

[API documentation](https://mirleft.github.io/ocaml-tls/)

### What is TLS?

Transport Layer Security (TLS) is probably the most widely deployed
Expand Down
6 changes: 3 additions & 3 deletions _oasis
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Document api
Type: ocamlbuild (0.3)
BuildTools+: ocamldoc
XOcamlbuildPath: doc
XOcamlbuildModules: lib/Engine, lib/Config, lib/Core,
lib/Ciphersuite, lib/Packet,
lib/Printer, lib/Reader, lib/Writer
XOcamlbuildModules: lib/Engine, lib/Config, lib/Packet, lib/Ciphersuite, lib/Core,
lwt/Tls_lwt, lwt/X509_lwt,
mirage/Tls_mirage
Install: false
12 changes: 6 additions & 6 deletions doc/api.odocl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# OASIS_START
# DO NOT EDIT (digest: e8f226e17a139e9ba7447b7917f28691)
# DO NOT EDIT (digest: 1fba321817ef3920b4184453a147f975)
lib/Engine
lib/Config
lib/Core
lib/Ciphersuite
lib/Packet
lib/Printer
lib/Reader
lib/Writer
lib/Ciphersuite
lib/Core
lwt/Tls_lwt
lwt/X509_lwt
mirage/Tls_mirage
# OASIS_STOP
2 changes: 1 addition & 1 deletion lib/ciphersuite.ml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(** Ciphersuite helper functions and definitions. Including mapping to reserved numbers and dissecting into key exchange, encryption, and hash algorithm. *)
(** Ciphersuite definitions and some helper functions. *)

(** sum type of all possible key exchange methods *)
type key_exchange_algorithm =
Expand Down
2 changes: 1 addition & 1 deletion lib/config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ let validate_certificate_chain = function
( match X509.Validation.verify_chain_of_trust ~anchors:[trust] (s :: ch) with
| `Ok _ -> ()
| `Fail x -> invalid ("certificate chain does not validate: " ^
(X509.Validation.certificate_failure_to_string x)) )
(X509.Validation.validation_error_to_string x)) )
| None -> () )
| _ -> invalid "certificate"

Expand Down
101 changes: 61 additions & 40 deletions lib/config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ open Core

(** Configuration of the TLS stack *)

(** {1 Config type} *)

(** certificate chain and private key of the first certificate *)
type certchain = X509.t list * Nocrypto.Rsa.priv

Expand All @@ -23,53 +25,24 @@ type config = private {
authenticator : X509.Authenticator.a option ; (** optional X509 authenticator *)
peer_name : string option ; (** optional name of other endpoint (used for SNI RFC4366) *)
own_certificates : own_cert ; (** optional default certificate chain and other certificate chains *)
} with sexp

module Ciphers : sig

open Ciphersuite

(** Cipher selection related utilities. *)

val default : ciphersuite list
(** All ciphersuites this library uses by default. *)

val supported : ciphersuite list
(** All ciphersuites this library implements. *)

val pfs : ciphersuite list
(** All perfect forward secrecy ciphersuites this library supports. *)

val pfs_of : ciphersuite list -> ciphersuite list
(** [pfs_of ciphers] selects all perfect forward secrecy ciphersuites from default. *)
end

(** [default_hashes] is a list of hash algorithms used by default *)
val default_hashes : Hash.hash list
}

(** [supported_hashes] is a list of supported hash algorithms by this library *)
val supported_hashes : Hash.hash list

(** [min_dh_size] is minimal diffie hellman group size in bits (currently 512) *)
val min_dh_size : int

(** [min_rsa_key_size] is minimal RSA modulus key size in bits (currently 1024) *)
val min_rsa_key_size : int
val config_of_sexp : Sexplib.Sexp.t -> config
val sexp_of_config : config -> Sexplib.Sexp.t

(** opaque type of a client configuration *)
type client with sexp
type client

(** opaque type of a server configuration *)
type server with sexp
val client_of_sexp : Sexplib.Sexp.t -> client
val sexp_of_client : client -> Sexplib.Sexp.t

(** [peer client name] is [client] with [name] as [peer_name] *)
val peer : client -> string -> client
(** opaque type of a server configuration *)
type server

(** [of_client client] is a client configuration for [client] *)
val of_client : client -> config
val server_of_sexp : Sexplib.Sexp.t -> server
val sexp_of_server : server -> Sexplib.Sexp.t

(** [of_server server] is a server configuration for [server] *)
val of_server : server -> config
(** {1 Constructors} *)

(** [client authenticator ?ciphers ?version ?hashes ?reneg ?certificates] is [client] configuration with the given parameters *)
(** @raise Invalid_argument if the configuration is invalid *)
Expand All @@ -92,3 +65,51 @@ val server :
?certificates : own_cert ->
?authenticator : X509.Authenticator.a ->
unit -> server

(** [peer client name] is [client] with [name] as [peer_name] *)
val peer : client -> string -> client

(** {1 Utility functions} *)

(** [default_hashes] is a list of hash algorithms used by default *)
val default_hashes : Hash.hash list

(** [supported_hashes] is a list of supported hash algorithms by this library *)
val supported_hashes : Hash.hash list

(** [min_dh_size] is minimal diffie hellman group size in bits (currently 512) *)
val min_dh_size : int

(** [min_rsa_key_size] is minimal RSA modulus key size in bits (currently 1024) *)
val min_rsa_key_size : int

(** Cipher selection *)
module Ciphers : sig

open Ciphersuite

(** Cipher selection related utilities. *)

(** {1 Cipher selection} *)

val default : ciphersuite list
(** All ciphersuites this library uses by default. *)

val supported : ciphersuite list
(** All ciphersuites this library implements. *)

val pfs : ciphersuite list
(** All perfect forward secrecy ciphersuites this library supports. *)

val pfs_of : ciphersuite list -> ciphersuite list
(** [pfs_of ciphers] selects all perfect forward secrecy ciphersuites from default. *)
end

(** {1 Internal use only} *)

(** [of_client client] is a client configuration for [client] *)
val of_client : client -> config

(** [of_server server] is a server configuration for [server] *)
val of_server : server -> config

2 changes: 2 additions & 0 deletions lib/core.ml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
(** Core type definitions *)

open Sexplib.Conv
open Nocrypto

Expand Down
8 changes: 4 additions & 4 deletions lib/engine.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ type fatal = State.fatal
type failure = State.failure with sexp

let alert_of_authentication_failure = function
| X509.Validation.SelfSigned _ -> Packet.UNKNOWN_CA
| X509.Validation.NoTrustAnchor -> Packet.UNKNOWN_CA
| X509.Validation.CertificateExpired _ -> Packet.CERTIFICATE_EXPIRED
| `SelfSigned _ -> Packet.UNKNOWN_CA
| `NoTrustAnchor -> Packet.UNKNOWN_CA
| `CertificateExpired _ -> Packet.CERTIFICATE_EXPIRED
| _ -> Packet.BAD_CERTIFICATE

let alert_of_error = function
| `NoConfiguredVersion _ -> Packet.PROTOCOL_VERSION
| `NoConfiguredCiphersuite _ -> Packet.HANDSHAKE_FAILURE
| `NoSecureRenegotiation -> Packet.HANDSHAKE_FAILURE
| `NoConfiguredHash _ -> Packet.HANDSHAKE_FAILURE
| `AuthenticationFailure err -> alert_of_authentication_failure err
| `NoMatchingCertificateFound _ -> Packet.HANDSHAKE_FAILURE
| `NoCertificateConfigured -> Packet.HANDSHAKE_FAILURE
| `CouldntSelectCertificate -> Packet.HANDSHAKE_FAILURE

let alert_of_fatal = function
| `NoSecureRenegotiation -> Packet.HANDSHAKE_FAILURE
| `MACUnderflow -> Packet.BAD_RECORD_MAC
| `MACMismatch -> Packet.BAD_RECORD_MAC
| `RecordOverflow _ -> Packet.RECORD_OVERFLOW
Expand Down
111 changes: 84 additions & 27 deletions lib/engine.mli
Original file line number Diff line number Diff line change
@@ -1,19 +1,48 @@
(** Core of pure library. This is the interface to effectful front-ends. *)
(** Transport layer security core.
[TLS] implements the transport layer security protocol entirely in
OCaml. TLS is used to secure a session between two endpoints, a
client and a server. This session can either be not authenticated
at all, or either, or both endpoints can be authenticated. Most
common is that the server is authenticated using X.509
certificates.
TLS is algorithmically agile: protocol version, key exchange
algorithm, symmetric cipher, and message authentication code are
negotiated upon connection.
This module [Engine] provides the pure core of the protocol
handling, and is used by the effectful front-ends. *)

(** {1 Constructors} *)

(** The abstract [state] type. *)
type state

(** [client client] is [tls * out] where [tls] is the initial state,
and [out] the initial client hello *)
val client : Config.client -> (state * Cstruct.t)

(** [server server] is [tls] where [tls] is the initial server
state *)
val server : Config.server -> state

(** {1 Protocol failures} *)

(** failures which can be mitigated by reconfiguration *)
type error = [
| `AuthenticationFailure of X509.Validation.certificate_failure
| `AuthenticationFailure of X509.Validation.validation_error
| `NoConfiguredCiphersuite of Ciphersuite.ciphersuite list
| `NoConfiguredVersion of Core.tls_version
| `NoConfiguredHash of Nocrypto.Hash.hash list
| `NoSecureRenegotiation
| `NoMatchingCertificateFound of string
| `NoCertificateConfigured
| `CouldntSelectCertificate
]

(** failures from received garbage or lack of features *)
type fatal = [
| `NoSecureRenegotiation
| `NoCiphersuite of Packet.any_ciphersuite list
| `NoVersion of Core.tls_any_version
| `ReaderError of Reader.error
Expand Down Expand Up @@ -53,52 +82,64 @@ type fatal = [
type failure = [
| `Error of error
| `Fatal of fatal
] with sexp
]

(** convert a failure to a tls alert *)
(** [alert_of_failure failure] is [alert], the TLS alert type for this failure. *)
val alert_of_failure : failure -> Packet.alert_type

(** convert a failure to a string *)
(** [string_of_failure failure] is [string], the string representation of the [failure]. *)
val string_of_failure : failure -> string

(** some abstract type a client gets *)
type state
(** [failure_of_sexp sexp] is [failure], the unmarshalled [sexp]. *)
val failure_of_sexp : Sexplib.Sexp.t -> failure

(** return type of handle_tls *)
type ret = [
(** [sexp_of_failure failure] is [sexp], the marshalled [failure]. *)
val sexp_of_failure : failure -> Sexplib.Sexp.t

(** {1 Protocol handling} *)

(** return 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. *)
type ret = [
| `Ok of [ `Ok of state | `Eof | `Alert of Packet.alert_type ]
* [ `Response of Cstruct.t option ]
* [ `Data of Cstruct.t option ]
(** success with either a new state, end of file, or an alert, a response to the communication partner and potential data for the application *)

| `Fail of failure * [ `Response of Cstruct.t ] (** fail with a failure, and a response to the other side *)
| `Fail of failure * [ `Response of Cstruct.t ]
]

(** [handle_tls tls in] is [ret], depending on incoming [tls] state and cstruct, return appropriate [ret] *)
val handle_tls : state -> Cstruct.t -> ret
(** [handle_tls state buffer] is [ret], depending on incoming [state]
and [buffer], return appropriate {!ret} *)
val handle_tls : state -> Cstruct.t -> ret

(** [can_handle_appdata tls] is a predicate which indicates when the connection has already completed a handshake *)
(** [can_handle_appdata state] is a predicate which indicates when the
connection has already completed a handshake. *)
val can_handle_appdata : state -> bool

(** [handshake_in_progress tls] is a predicate which indicates whether a handshake is in progress *)
(** [handshake_in_progress tls] is a predicate which indicates whether
a handshake is in progress. *)
val handshake_in_progress : state -> bool

(** [send_application_data tls outs] is [(tls' * out) option] where [tls'] is the new tls state, and [out] the cstruct to send over the wire (encrypted and wrapped [outs]) *)
(** [send_application_data tls outs] is [(tls' * out) option] where
[tls'] is the new tls state, and [out] the cstruct to send over the
wire (encrypted and wrapped [outs]) *)
val send_application_data : state -> Cstruct.t list -> (state * Cstruct.t) option

(** [send_close_notify tls] is [tls' * out] where [tls'] is the new tls state, and out the (possible encrypted) close notify alert *)
(** [send_close_notify tls] is [tls' * out] where [tls'] is the new
tls state, and out the (possible encrypted) close notify alert *)
val send_close_notify : state -> state * Cstruct.t

(** [reneg tls] is [(tls' * out) option] where [tls'] is the new tls state, and out either a client hello or hello request (depending on the communication endpoint we are) *)
(** [reneg tls] is [(tls' * out) option] where [tls'] is the new tls
state, and out either a client hello or hello request (depending on
the communication endpoint we are) *)
val reneg : state -> (state * Cstruct.t) option

(** [client client] is [tls * out] where [tls] is the initial state, and [out] the initial client hello *)
val client : Config.client -> (state * Cstruct.t)

(** [server server] is [tls] where [tls] is the initial server state *)
val server : Config.server -> state
(** {1 Session information} *)

(** information about an open session *)
type epoch_data = {
protocol_version : Core.tls_version ;
ciphersuite : Ciphersuite.ciphersuite ;
Expand All @@ -109,11 +150,27 @@ type epoch_data = {
own_private_key : Nocrypto.Rsa.priv option ;
own_name : string option ;
master_secret : State.master_secret ;
} with sexp
}

(** [epoch_data_of_sexp sexp] is [epoch_data], the unmarshalled [sexp]. *)
val epoch_data_of_sexp : Sexplib.Sexp.t -> epoch_data

(** [sexp_of_epoch_data epoch_data] is [sexp], the marshalled [epoch_data]. *)
val sexp_of_epoch_data : epoch_data -> Sexplib.Sexp.t

(** polymorphic variant, only the second should ever be visible to an
application. *)
type epoch = [
| `InitialEpoch
| `Epoch of epoch_data
] with sexp
]

(** [epoch_of_sexp sexp] is [epoch], the unmarshalled [sexp]. *)
val epoch_of_sexp : Sexplib.Sexp.t -> epoch

(** [sexp_of_epoch epoch] is [sexp], the marshalled [epoch]. *)
val sexp_of_epoch : epoch -> Sexplib.Sexp.t

(** [epoch state] is [epoch], which contains the session
information. *)
val epoch : state -> epoch
2 changes: 1 addition & 1 deletion lib/handshake_client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ let answer_server_hello_renegotiate state session ch (sh : server_hello) raw log
let validate_reneg reneg data =
match reneg, data with
| (cvd, svd), Some x -> guard (Cs.equal (cvd <+> svd) x) (`Fatal `InvalidRenegotiation)
| _ -> fail (`Error `NoSecureRenegotiation)
| _ -> fail (`Fatal `NoSecureRenegotiation)
in

let cfg = state.config in
Expand Down
Loading

0 comments on commit 31a7e6a

Please sign in to comment.