-
Notifications
You must be signed in to change notification settings - Fork 0
/
DY.Example.DH.Protocol.Stateful.fst
146 lines (125 loc) · 5.94 KB
/
DY.Example.DH.Protocol.Stateful.fst
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
module DY.Example.DH.Protocol.Stateful
open Comparse
open DY.Core
open DY.Lib
open DY.Example.DH.Protocol.Total
(*** Definition of state ***)
[@@ with_bytes bytes]
type dh_session =
| InitiatorSentMsg1: b:principal -> x:bytes -> dh_session
| ResponderSentMsg2: a:principal -> gx:bytes -> gy:bytes -> y:bytes -> dh_session
| InitiatorSendMsg3: b:principal -> gx:bytes -> gy:bytes -> k:bytes -> dh_session
| ResponderReceivedMsg3: a:principal -> gx:bytes -> gy:bytes -> k:bytes -> dh_session
%splice [ps_dh_session] (gen_parser (`dh_session))
%splice [ps_dh_session_is_well_formed] (gen_is_well_formed_lemma (`dh_session))
instance dh_session_parseable_serializeable: parseable_serializeable bytes dh_session
= mk_parseable_serializeable ps_dh_session
(*** Definition of events ***)
[@@ with_bytes bytes]
type dh_event =
| Initiate1: a:principal -> b:principal -> x:bytes -> dh_event
| Respond1: a:principal -> b:principal -> gx:bytes -> gy:bytes -> y:bytes -> dh_event
| Initiate2: a:principal -> b:principal -> gx:bytes -> gy:bytes -> k:bytes -> dh_event
| Respond2: a:principal -> b:principal -> gx:bytes -> gy:bytes -> k:bytes -> dh_event
%splice [ps_dh_event] (gen_parser (`dh_event))
%splice [ps_dh_event_is_well_formed] (gen_is_well_formed_lemma (`dh_event))
instance dh_event_instance: event dh_event = {
tag = "DH.Event";
format = mk_parseable_serializeable ps_dh_event;
}
(*** Setup for the stateful code ***)
instance local_state_dh_session: local_state dh_session = {
tag = "DH.Session";
format = mk_parseable_serializeable ps_dh_session;
}
type dh_global_sess_ids = {
pki: state_id;
private_keys: state_id;
}
(*** Labels used to generate randomness ***)
val ephemeral_dh_key_label:
principal -> state_id ->
label
let ephemeral_dh_key_label prin sess_id =
principal_tag_state_label prin "DH.Session" sess_id
(*** Stateful code ***)
// Alice prepares message 1
//
// This method is separated from the send_msg1 method
// to give the attacker more flexibility. With this
// separation an attacker can set a state without sending
// a message over the network.
val prepare_msg1: principal -> principal -> traceful state_id
let prepare_msg1 alice bob =
let* alice_si = new_session_id alice in
let* x = mk_rand (DhKey "DH.dh_key" empty) (ephemeral_dh_key_label alice alice_si) 32 in
trigger_event alice (Initiate1 alice bob x);*
set_state alice alice_si (InitiatorSentMsg1 bob x <: dh_session);*
return alice_si
// Alice sends message 1
val send_msg1: principal -> state_id -> traceful (option nat)
let send_msg1 alice alice_si =
let*? session_state = get_state alice alice_si in
guard_tr (InitiatorSentMsg1? session_state);*?
let InitiatorSentMsg1 bob x = session_state in
let msg = compute_message1 alice x in
let* msg_id = send_msg msg in
return (Some msg_id)
// Bob prepares message 2
val prepare_msg2: principal -> principal -> nat -> traceful (option state_id)
let prepare_msg2 alice bob msg_id =
let*? msg = recv_msg msg_id in
let*? msg1: message1 = return (decode_message1 msg) in
let* bob_si = new_session_id bob in
let* y = mk_rand (DhKey "DH.dh_key" empty) (ephemeral_dh_key_label bob bob_si) 32 in
trigger_event bob (Respond1 alice bob msg1.gx (dh_pk y) y);*
set_state bob bob_si (ResponderSentMsg2 alice msg1.gx (dh_pk y) y <: dh_session);*
return (Some bob_si)
// Bob sends message 2
val send_msg2: dh_global_sess_ids -> principal -> state_id -> traceful (option nat)
let send_msg2 global_sess_id bob bob_si =
let*? session_state = get_state bob bob_si in
guard_tr (ResponderSentMsg2? session_state);*?
let ResponderSentMsg2 alice gx gy y = session_state in
let*? sk_b = get_private_key bob global_sess_id.private_keys (LongTermSigKey "DH.SigningKey") in
let* n_sig = mk_rand SigNonce (long_term_key_label bob) 32 in
let msg = compute_message2 alice bob gx gy sk_b n_sig in
let* msg_id = send_msg msg in
return (Some msg_id)
// Alice prepares message 3
//
// This function has to verify the signature from message 2
val prepare_msg3: dh_global_sess_ids -> principal -> state_id -> principal -> nat -> traceful (option unit)
let prepare_msg3 global_sess_id alice alice_si bob msg_id =
let*? session_state = get_state alice alice_si in
guard_tr (InitiatorSentMsg1? session_state);*?
let InitiatorSentMsg1 bob x = session_state in
let*? pk_b = get_public_key alice global_sess_id.pki (LongTermSigKey "DH.SigningKey") bob in
let*? msg = recv_msg msg_id in
let*? res:verify_msg2_result = return (decode_and_verify_message2 msg alice x pk_b) in
trigger_event alice (Initiate2 alice bob res.gx res.gy res.k);*
set_state alice alice_si (InitiatorSendMsg3 bob res.gx res.gy res.k <: dh_session);*
return (Some ())
// Alice send message 3
val send_msg3: dh_global_sess_ids -> principal -> principal -> state_id -> traceful (option nat)
let send_msg3 global_sess_id alice bob alice_si =
let*? session_state = get_state alice alice_si in
guard_tr (InitiatorSendMsg3? session_state);*?
let InitiatorSendMsg3 bob gx gy x = session_state in
let*? sk_a = get_private_key alice global_sess_id.private_keys (LongTermSigKey "DH.SigningKey") in
let* n_sig = mk_rand SigNonce (long_term_key_label alice) 32 in
let msg = compute_message3 alice bob gx gy sk_a n_sig in
let* msg_id = send_msg msg in
return (Some msg_id)
// Bob verifies message 3
val verify_msg3: dh_global_sess_ids -> principal -> principal -> nat -> state_id -> traceful (option unit)
let verify_msg3 global_sess_id alice bob msg_id bob_si =
let*? session_state = get_state bob bob_si in
guard_tr (ResponderSentMsg2? session_state);*?
let ResponderSentMsg2 alice gx gy y = session_state in
let*? pk_a = get_public_key bob global_sess_id.pki (LongTermSigKey "DH.SigningKey") alice in
let*? msg = recv_msg msg_id in
let*? res:verify_msg3_result = return (decode_and_verify_message3 msg bob gx gy y pk_a) in
trigger_event bob (Respond2 alice bob gx gy res.k);*
set_state bob bob_si (ResponderReceivedMsg3 alice gx gy res.k <: dh_session);*
return (Some ())