Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session hash #287

Merged
merged 5 commits into from
Sep 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/core.ml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type extension =
| Padding of int
| SignatureAlgorithms of (Hash.hash * signature_algorithm_type) list
| UnknownExtension of (int * Cstruct.t)
| ExtendedMasterSecret
with sexp

type ('a, 'b) hello = {
Expand Down Expand Up @@ -178,4 +179,5 @@ type epoch_data = {
own_name : string option ;
master_secret : master_secret ;
session_id : SessionID.t ;
extended_ms : bool ;
} with sexp
1 change: 1 addition & 0 deletions lib/engine.ml
Original file line number Diff line number Diff line change
Expand Up @@ -581,4 +581,5 @@ let epoch state =
own_name = session.own_name ;
master_secret = session.master_secret ;
session_id = session.session_id ;
extended_ms = session.extended_ms ;
}
40 changes: 25 additions & 15 deletions lib/handshake_client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ let default_client_hello config =
| TLS_1_2 -> cs
and sessionid =
match config.cached_session with
| None -> None
| Some { session_id ; _ } -> Some session_id
| Some { session_id ; extended_ms ; _ } when extended_ms = true -> Some session_id
| _ -> None
in
let ch = {
version = Supported version ;
random = Rng.generate 32 ;
sessionid = sessionid ;
ciphersuites = List.map Ciphersuite.ciphersuite_to_any_ciphersuite ciphers ;
extensions = host @ signature_algos
extensions = host @ signature_algos @ [ExtendedMasterSecret]
}
in
(ch , version)
Expand Down Expand Up @@ -66,7 +66,9 @@ let answer_server_hello state ch (sh : server_hello) raw log =
let epoch_matches (epoch : epoch_data) =
epoch.ciphersuite = sh.ciphersuites &&
epoch.protocol_version = sh.version &&
option false ((=) epoch.session_id) sh.sessionid
option false ((=) epoch.session_id) sh.sessionid &&
List.mem ExtendedMasterSecret sh.extensions &&
epoch.extended_ms
in

match state.config.cached_session with
Expand All @@ -87,12 +89,17 @@ let answer_server_hello state ch (sh : server_hello) raw log =
let machina =
let cipher = sh.ciphersuites in
let session_id = match sh.sessionid with None -> Cstruct.create 0 | Some x -> x in
let extended_ms =
let ems = List.mem ExtendedMasterSecret in
ems ch.extensions && ems sh.extensions
in
let session = { empty_session with
client_random = ch.random ;
client_version = ch.version ;
server_random = sh.random ;
ciphersuite = cipher ;
session_id ;
extended_ms ;
}
in
Ciphersuite.(match ciphersuite_kex cipher with
Expand Down Expand Up @@ -244,13 +251,6 @@ let answer_certificate_request state session cr kex pms raw log =
let answer_server_hello_done state session sigalgs kex premaster raw log =
let kex = ClientKeyExchange kex in
let ckex = Writer.assemble_handshake kex in
let master_secret =
Handshake_crypto.derive_master_secret state.protocol_version session premaster
in
let session = { session with master_secret } in
let client_ctx, server_ctx =
Handshake_crypto.initialise_crypto_ctx state.protocol_version session
in

( match session.client_auth, session.own_private_key with
| true, Some p ->
Expand All @@ -265,14 +265,24 @@ let answer_server_hello_done state session sigalgs kex premaster raw log =
let ccert_verify = Writer.assemble_handshake cert_verify in
([ cert ; kex ; cert_verify ],
[ ccert ; ckex ; ccert_verify ],
to_sign @ [ ccert_verify ])
to_sign, Some ccert_verify)
| true, None ->
let cert = Certificate [] in
let ccert = Writer.assemble_handshake cert in
return ([cert ; kex], [ccert ; ckex], log @ [ raw ; ccert ; ckex ])
return ([cert ; kex], [ccert ; ckex], log @ [ raw ; ccert ; ckex ], None)
| false, _ ->
return ([kex], [ckex], log @ [ raw ; ckex ]) )
>|= fun (msgs, raw_msgs, to_fin) ->
return ([kex], [ckex], log @ [ raw ; ckex ], None) )
>|= fun (msgs, raw_msgs, raws, cert_verify) ->

let to_fin = raws @ option [] (fun x -> [x]) cert_verify in

let master_secret =
Handshake_crypto.derive_master_secret state.protocol_version session premaster raws
in
let session = { session with master_secret } in
let client_ctx, server_ctx =
Handshake_crypto.initialise_crypto_ctx state.protocol_version session
in

let checksum = Handshake_crypto.finished state.protocol_version master_secret "client finished" to_fin in
let fin = Finished checksum in
Expand Down
5 changes: 4 additions & 1 deletion lib/handshake_common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let empty_session = {
renegotiation = Cstruct.(create 0, create 0) ;
client_auth = false ;
session_id = Cstruct.create 0 ;
extended_ms = false ;
}

let session_of_epoch (epoch : epoch_data) : session_data = {
Expand All @@ -49,7 +50,8 @@ let session_of_epoch (epoch : epoch_data) : session_data = {
own_private_key = epoch.own_private_key ;
master_secret = epoch.master_secret ;
own_name = epoch.own_name ;
session_id = epoch.session_id
session_id = epoch.session_id ;
extended_ms = epoch.extended_ms ;
}

let supported_protocol_version (min, max) v =
Expand All @@ -67,6 +69,7 @@ let to_ext_type = function
| Padding _ -> `Padding
| SignatureAlgorithms _ -> `SignatureAlgorithms
| UnknownExtension _ -> `UnknownExtension
| ExtendedMasterSecret -> `ExtendedMasterSecret

let extension_types exts = List.(
exts |> map to_ext_type
Expand Down
20 changes: 12 additions & 8 deletions lib/handshake_crypto.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ let pseudo_random_function version len secret label seed =
and sha = p_hash (SHA1.hmac, 20) s2 labelled len in
Cs.xor md5 sha

let generate_master_secret version pre_master_secret seed =
pseudo_random_function version 48 pre_master_secret "master secret" seed

let key_block version len master_secret seed =
pseudo_random_function version len master_secret "key expansion" seed

Expand All @@ -58,11 +55,18 @@ let divide_keyblock key mac iv buf =
in
(c_mac, s_mac, c_key, s_key, c_iv, s_iv)

let derive_master_secret version session premaster =
let client_random = session.client_random
and server_random = session.server_random
in
generate_master_secret version premaster (client_random <+> server_random)
let derive_master_secret version session premaster log =
let prf = pseudo_random_function version 48 premaster in
if session.extended_ms then
let session_hash =
let data = Utils.Cs.appends log in
match version with
| TLS_1_0 | TLS_1_1 -> MD5.digest data <+> SHA1.digest data
| TLS_1_2 -> SHA256.digest data
in
prf "extended master secret" session_hash
else
prf "master secret" (session.client_random <+> session.server_random)

let initialise_crypto_ctx version session =
let open Ciphersuite in
Expand Down
2 changes: 1 addition & 1 deletion lib/handshake_crypto.mli
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
open State

val derive_master_secret : Core.tls_version -> session_data -> Cstruct.t -> Core.master_secret
val derive_master_secret : Core.tls_version -> session_data -> Cstruct.t -> Cstruct.t list -> Core.master_secret
val initialise_crypto_ctx : Core.tls_version -> session_data -> (crypto_context * crypto_context)
val finished : Core.tls_version -> Cstruct.t -> string -> Cstruct.t list -> Cstruct.t
26 changes: 18 additions & 8 deletions lib/handshake_server.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,18 @@ let answer_client_finished_resume state session server_verify client_fin raw log
({ state with machina ; session = session :: state.session }, [])

let establish_master_secret state session premastersecret raw log =
let log = log @ [raw] in
let master_secret = Handshake_crypto.derive_master_secret
state.protocol_version session premastersecret
state.protocol_version session premastersecret log
in
let session = { session with master_secret = master_secret } in
let client_ctx, server_ctx =
Handshake_crypto.initialise_crypto_ctx state.protocol_version session
in
let machina =
match session.peer_certificate with
| [] -> AwaitClientChangeCipherSpec (session, server_ctx, client_ctx, log @ [raw])
| _ -> AwaitClientCertificateVerify (session, server_ctx, client_ctx, log @ [raw])
| [] -> AwaitClientChangeCipherSpec (session, server_ctx, client_ctx, log)
| _ -> AwaitClientCertificateVerify (session, server_ctx, client_ctx, log)
in
(* Tracing.cs ~tag:"master-secret" master_secret ; *)
({ state with machina = Server machina }, [])
Expand Down Expand Up @@ -172,6 +173,10 @@ let server_hello session version reneg =
and secren = match reneg with
| None -> SecureRenegotiation (Cstruct.create 0)
| Some (cvd, svd) -> SecureRenegotiation (cvd <+> svd)
and ems = if session.extended_ms then
[ExtendedMasterSecret]
else
[]
and session_id =
match Cstruct.len session.session_id with
| 0 -> Rng.generate 32
Expand All @@ -182,7 +187,7 @@ let server_hello session version reneg =
random = server_random ;
sessionid = Some session_id ;
ciphersuites = session.ciphersuite ;
extensions = secren :: host }
extensions = secren :: host @ ems }
in
(* Tracing.sexpf ~tag:"handshake-out" ~f:sexp_of_tls_handshake sh ; *)
(Writer.assemble_handshake sh,
Expand All @@ -207,6 +212,8 @@ let answer_client_hello_common state reneg ch raw =
| Some _ -> fail (`Error (`NoConfiguredCiphersuite cciphers))
| None -> fail (`Fatal (`NoCiphersuite ch.ciphersuites)) ) >|= fun cipher ->

let extended_ms = List.mem ExtendedMasterSecret ch.extensions in

(* Tracing.sexpf ~tag:"cipher" ~f:Ciphersuite.sexp_of_ciphersuite cipher ; *)

{ empty_session with
Expand All @@ -215,7 +222,8 @@ let answer_client_hello_common state reneg ch raw =
ciphersuite = cipher ;
own_certificate = chain ;
own_private_key = priv ;
own_name = host }
own_name = host ;
extended_ms = extended_ms }

and server_cert session =
match session.own_certificate with
Expand Down Expand Up @@ -313,14 +321,16 @@ let answer_client_hello state (ch : client_hello) raw =


and resume ch state =
let epoch_matches (epoch : Core.epoch_data) version ciphers =
let epoch_matches (epoch : Core.epoch_data) version ciphers extensions =
let cciphers = filter_map ~f:Ciphersuite.any_ciphersuite_to_ciphersuite ciphers in
List.mem epoch.ciphersuite cciphers &&
version = epoch.protocol_version
version = epoch.protocol_version &&
List.mem ExtendedMasterSecret extensions &&
epoch.extended_ms
in

match option None state.config.session_cache ch.sessionid with
| Some epoch when epoch_matches epoch state.protocol_version ch.ciphersuites ->
| Some epoch when epoch_matches epoch state.protocol_version ch.ciphersuites ch.extensions ->
Some { session_of_epoch epoch with
client_random = ch.random ;
client_version = ch.version ;
Expand Down
5 changes: 5 additions & 0 deletions lib/reader.ml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ let parse_extension raw =
raise_trailing_bytes "signature algorithms"
else
SignatureAlgorithms algos
| Some EXTENDED_MASTER_SECRET ->
if len buf > 0 then
raise_trailing_bytes "extended master secret"
else
ExtendedMasterSecret
| _ ->
UnknownExtension (etype, buf)
in
Expand Down
1 change: 1 addition & 0 deletions lib/state.ml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type session_data = {
own_name : string option ;
client_auth : bool ;
session_id : Cstruct.t ;
extended_ms : bool ;
} with sexp

(* state machine of the server *)
Expand Down
1 change: 1 addition & 0 deletions lib/writer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ let assemble_extension e =
(buf, PADDING)
| SignatureAlgorithms s ->
(assemble_signature_algorithms s, SIGNATURE_ALGORITHMS)
| ExtendedMasterSecret -> (Cstruct.create 0, EXTENDED_MASTER_SECRET)
in
let buf = create 4 in
BE.set_uint16 buf 0 (extension_type_to_int typ);
Expand Down
Loading