-
Notifications
You must be signed in to change notification settings - Fork 68
/
Copy pathstate.ml
132 lines (109 loc) · 5.76 KB
/
state.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
(* Defines all high-level datatypes for the TLS library. It is opaque to clients
of this library, and only used from within the library. *)
open Sexplib
open Sexplib.Conv
open Core
open Nocrypto
(* initialisation vector style, depending on TLS version *)
type iv_mode =
| Iv of Cstruct_s.t (* traditional CBC (reusing last cipherblock) *)
| Random_iv (* TLS 1.1 and higher explicit IV (we use random) *)
with sexp
(* state of a symmetric cipher *)
type cipher_st =
| Stream : 'k Crypto.stream_cipher * 'k -> cipher_st (* stream cipher state *)
| CBC : 'k Crypto.cbc_cipher * 'k * iv_mode -> cipher_st (* block cipher state *)
(* | GCM : ... *)
(* context of a TLS connection (both in and out has each one of these) *)
type crypto_context = {
sequence : int64 ; (* sequence number *)
cipher_st : cipher_st ; (* cipher state *)
mac : Crypto.hash_fn * Cstruct.t (* hmac state *)
}
(* Sexplib stubs -- rethink how to play with crypto. *)
let sexp_of_cipher_st = function
| Stream _ -> Sexp.(Atom "<stream-state>")
| CBC (_, _, ivm) -> Sexp.(List [Atom "<cbc-state>"; sexp_of_iv_mode ivm])
let crypto_context_of_sexp _ = failwith "can't parse crypto context from sexp"
and sexp_of_crypto_context cc =
Sexp_ext.record [
"sequence" , sexp_of_int64 cc.sequence ;
"cipher_st", sexp_of_cipher_st cc.cipher_st ;
"mac" , Cstruct_s.sexp_of_t (snd cc.mac)
]
(* *** *)
(* the raw handshake log we need to carry around *)
type hs_log = Cstruct_s.t list with sexp
(* the master secret of a TLS connection *)
type master_secret = Cstruct_s.t with sexp
(* diffie hellman group and secret *)
type dh_sent = DH.group * DH.secret with sexp
(* persistent information during a handshake *)
type handshake_params = {
server_random : Cstruct_s.t ; (* 32 bytes random from the server hello *)
client_random : Cstruct_s.t ; (* 32 bytes random from the client hello *)
client_version : tls_version ; (* version in client hello (needed in RSA client key exchange) *)
cipher : Ciphersuite.ciphersuite (* selected ciphersuite by the server *)
} with sexp
(* state machine of the server *)
type server_handshake_state =
| AwaitClientHello (* initial state *)
| AwaitClientKeyExchange_RSA of handshake_params * hs_log (* server hello done is sent, and RSA key exchange used, waiting for a client key exchange message *)
| AwaitClientKeyExchange_DHE_RSA of handshake_params * dh_sent * hs_log (* server hello done is sent, and DHE_RSA key exchange used, waiting for client key exchange *)
| AwaitClientChangeCipherSpec of crypto_context * crypto_context * master_secret * hs_log (* client key exchange received, next should be change cipher spec *)
| AwaitClientFinished of master_secret * hs_log (* change cipher spec received, next should be the finished including a hmac over all handshake packets *)
| Established (* handshake successfully completed *)
with sexp
(* state machine of the client *)
type client_handshake_state =
| ClientInitial (* initial state *)
| AwaitServerHello of client_hello * handshake_params * hs_log (* client hello is sent, handshake_params are half-filled *)
| AwaitCertificate_RSA of handshake_params * hs_log (* certificate expected with RSA key exchange *)
| AwaitCertificate_DHE_RSA of handshake_params * hs_log (* certificate expected with DHE_RSA key exchange *)
| AwaitServerKeyExchange_DHE_RSA of handshake_params * Certificate.certificate * hs_log (* server key exchange expected with DHE_RSA *)
| AwaitServerHelloDone of handshake_params * Cstruct_s.t * Cstruct_s.t * hs_log (* server hello done expected, client key exchange and premastersecret are ready *)
| AwaitServerChangeCipherSpec of crypto_context * Cstruct_s.t * master_secret * hs_log (* change cipher spec expected *)
| AwaitServerFinished of Cstruct_s.t * master_secret * hs_log (* finished expected with a hmac over all handshake packets *)
| Established (* handshake successfully completed *)
with sexp
type handshake_machina_state =
| Client of client_handshake_state
| Server of server_handshake_state
with sexp
(* a collection of client and server verify bytes for renegotiation *)
type reneg_params = Cstruct_s.t * Cstruct_s.t
with sexp
(* state during a handshake, used in the handlers *)
type handshake_state = {
version : tls_version ; (* negotiated version *)
machina : handshake_machina_state ; (* state machine state *)
config : Config.config ; (* given config *)
reneg : reneg_params option ; (* renegotiation data *)
hs_fragment : Cstruct_s.t (* handshake messages can be fragmented, leftover from before *)
} with sexp
(* connection state: initially None, after handshake a crypto context *)
type crypto_state = crypto_context option
with sexp
(* record consisting of a content type and a byte vector *)
type record = Packet.content_type * Cstruct_s.t with sexp
(* response returned by a handler *)
type rec_resp = [
| `Change_enc of crypto_state (* either instruction to change the encryptor to the given one *)
| `Record of record (* or a record which should be sent out *)
]
(* response for the decryption part *)
type dec_resp = [
| `Change_dec of crypto_state (* either change the decryptor to the given one *)
| `Pass (* do not change anything *)
]
(* return type of handshake handlers *)
type handshake_return = handshake_state * rec_resp list
(* return type of change cipher spec handlers *)
type ccs_return = handshake_state * rec_resp list * dec_resp
(* Top level state, encapsulating the entire session. *)
type state = {
handshake : handshake_state ; (* the current handshake state *)
decryptor : crypto_state ; (* the current decryption state *)
encryptor : crypto_state ; (* the current encryption state *)
fragment : Cstruct_s.t ; (* the leftover fragment from TCP fragmentation *)
} with sexp