Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
handshake_crypto.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
open Mirage_crypto.Hash open State let (<+>) = Cstruct.append let halve secret = let size = Cstruct.length secret in let half = size - size / 2 in Cstruct.(sub secret 0 half, sub secret (size - half) half) let p_hash (hmac, hmac_n) key seed len = let rec expand a to_go = let res = hmac ~key (a <+> seed) in if to_go > hmac_n then res <+> expand (hmac ~key a) (to_go - hmac_n) else Cstruct.sub res 0 to_go in expand (hmac ~key seed) len let prf_mac = function | `RSA_WITH_AES_256_GCM_SHA384 | `DHE_RSA_WITH_AES_256_GCM_SHA384 | `ECDHE_RSA_WITH_AES_256_GCM_SHA384 | `ECDHE_RSA_WITH_AES_256_CBC_SHA384 | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 | `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -> (module SHA384 : S) | _ -> (module SHA256 : S) let pseudo_random_function version cipher len secret label seed = let labelled = Cstruct.of_string label <+> seed in match version with | `TLS_1_1 | `TLS_1_0 -> let (s1, s2) = halve secret in let md5 = p_hash (MD5.hmac, MD5.digest_size) s1 labelled len and sha = p_hash (SHA1.hmac, SHA1.digest_size) s2 labelled len in Mirage_crypto.Uncommon.Cs.xor md5 sha | `TLS_1_2 -> let module D = (val (prf_mac cipher)) in p_hash (D.hmac, D.digest_size) secret labelled len let key_block version cipher len master_secret seed = pseudo_random_function version cipher len master_secret "key expansion" seed let hash version cipher data = match version with | `TLS_1_0 | `TLS_1_1 -> MD5.digest data <+> SHA1.digest data | `TLS_1_2 -> let module H = (val (prf_mac cipher)) in H.digest data let finished version cipher master_secret label ps = let data = Cstruct.concat ps in let seed = hash version cipher data in pseudo_random_function version cipher 12 master_secret label seed let divide_keyblock key mac iv buf = let open Cstruct in let c_mac, rt0 = split buf mac in let s_mac, rt1 = split rt0 mac in let c_key, rt2 = split rt1 key in let s_key, rt3 = split rt2 key in let c_iv , s_iv = split rt3 iv in (c_mac, s_mac, c_key, s_key, c_iv, s_iv) let derive_master_secret version (session : session_data) premaster log = let prf = pseudo_random_function version session.ciphersuite 48 premaster in if session.extended_ms then let session_hash = let data = Cstruct.concat log in hash version session.ciphersuite data in prf "extended master secret" session_hash else prf "master secret" (session.common_session_data.client_random <+> session.common_session_data.server_random) let initialise_crypto_ctx version (session : session_data) = let open Ciphersuite in let client_random = session.common_session_data.client_random and server_random = session.common_session_data.server_random and master = session.common_session_data.master_secret and cipher = session.ciphersuite in let pp = ciphersuite_privprot cipher in let c_mac, s_mac, c_key, s_key, c_iv, s_iv = let iv_l = match version with | `TLS_1_0 -> Some () | _ -> None in let key_len, iv_len, mac_len = Ciphersuite.key_length iv_l pp in let kblen = 2 * key_len + 2 * mac_len + 2 * iv_len and rand = server_random <+> client_random in let keyblock = key_block version cipher kblen master rand in divide_keyblock key_len mac_len iv_len keyblock in let context cipher_k iv mac_k = let open Crypto.Ciphers in let cipher_st = let iv_mode = match version with | `TLS_1_0 -> Iv iv | _ -> Random_iv in get_cipher ~secret:cipher_k ~hmac_secret:mac_k ~iv_mode ~nonce:iv pp and sequence = 0L in { cipher_st ; sequence } in let c_context = context c_key c_iv c_mac and s_context = context s_key s_iv s_mac in (c_context, s_context)