1use cypher::Ecdh;
23
24#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
25pub enum InitiatorPattern {
26 #[display("N")]
27 No,
28
29 #[display("X")]
30 Xmitted,
31
32 #[display("K")]
33 Known,
34
35 #[display("I")]
36 Immediately,
37}
38
39#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
40pub enum OneWayPattern {
41 #[display("N")]
42 No,
43
44 #[display("X")]
45 Xmitted,
46
47 #[display("L")]
48 Known,
49}
50
51#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
52pub enum PreMsgKeyPat {
53 #[display("-> s")]
54 InitiatorStatic,
55
56 #[display("<- s")]
57 ResponderStatic,
58
59 #[display("")]
60 Empty,
61}
62
63#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
64#[display("{initiator}{responder}")]
65pub struct HandshakePattern {
66 pub initiator: InitiatorPattern,
67 pub responder: OneWayPattern,
68}
69
70impl HandshakePattern {
71 pub fn nn() -> Self {
72 Self {
73 initiator: InitiatorPattern::No,
74 responder: OneWayPattern::No,
75 }
76 }
77
78 pub fn pre_messages(self) -> &'static [PreMsgKeyPat] {
79 match (self.initiator, self.responder) {
80 (InitiatorPattern::No, OneWayPattern::No) => &[PreMsgKeyPat::Empty],
81 (InitiatorPattern::No, OneWayPattern::Known) => &[PreMsgKeyPat::ResponderStatic],
82 (InitiatorPattern::No, OneWayPattern::Xmitted) => &[PreMsgKeyPat::Empty],
83 (InitiatorPattern::Xmitted, OneWayPattern::No) => &[PreMsgKeyPat::Empty],
84 (InitiatorPattern::Xmitted, OneWayPattern::Known) => &[PreMsgKeyPat::ResponderStatic],
85 (InitiatorPattern::Xmitted, OneWayPattern::Xmitted) => &[PreMsgKeyPat::Empty],
86 (InitiatorPattern::Known, OneWayPattern::No) => &[PreMsgKeyPat::InitiatorStatic],
87 (InitiatorPattern::Known, OneWayPattern::Known) => {
88 &[PreMsgKeyPat::InitiatorStatic, PreMsgKeyPat::ResponderStatic]
89 }
90 (InitiatorPattern::Known, OneWayPattern::Xmitted) => &[PreMsgKeyPat::InitiatorStatic],
91 (InitiatorPattern::Immediately, OneWayPattern::No) => &[PreMsgKeyPat::Empty],
92 (InitiatorPattern::Immediately, OneWayPattern::Known) => {
93 &[PreMsgKeyPat::InitiatorStatic]
94 }
95 (InitiatorPattern::Immediately, OneWayPattern::Xmitted) => &[PreMsgKeyPat::Empty],
96 }
97 }
98
99 pub fn message_patterns(self, is_initiator: bool) -> &'static [&'static [MessagePattern]] {
100 if is_initiator {
101 match (self.initiator, self.responder) {
102 (InitiatorPattern::No, OneWayPattern::No) => &[&[MessagePattern::E]],
103 (InitiatorPattern::No, OneWayPattern::Known) => {
104 &[&[MessagePattern::E, MessagePattern::ES]]
105 }
106 (InitiatorPattern::No, OneWayPattern::Xmitted) => &[&[MessagePattern::E]],
107 (InitiatorPattern::Xmitted, OneWayPattern::No) => {
108 &[&[MessagePattern::E], &[MessagePattern::S, MessagePattern::SE]]
109 }
110 (InitiatorPattern::Xmitted, OneWayPattern::Known) => &[
111 &[MessagePattern::E, MessagePattern::ES],
112 &[MessagePattern::S, MessagePattern::SE],
113 ],
114 (InitiatorPattern::Xmitted, OneWayPattern::Xmitted) => {
115 &[&[MessagePattern::E], &[MessagePattern::S, MessagePattern::SE]]
116 }
117 (InitiatorPattern::Known, OneWayPattern::No) => &[&[MessagePattern::E]],
118 (InitiatorPattern::Known, OneWayPattern::Known) => {
119 &[&[MessagePattern::E, MessagePattern::ES, MessagePattern::SS]]
120 }
121 (InitiatorPattern::Known, OneWayPattern::Xmitted) => &[&[MessagePattern::E]],
122 (InitiatorPattern::Immediately, OneWayPattern::No) => {
123 &[&[MessagePattern::E, MessagePattern::S]]
124 }
125 (InitiatorPattern::Immediately, OneWayPattern::Known) => &[&[
126 MessagePattern::E,
127 MessagePattern::ES,
128 MessagePattern::S,
129 MessagePattern::SS,
130 ]],
131 (InitiatorPattern::Immediately, OneWayPattern::Xmitted) => {
132 &[&[MessagePattern::E, MessagePattern::S]]
133 }
134 }
135 } else {
136 match (self.initiator, self.responder) {
137 (InitiatorPattern::No, OneWayPattern::No) => {
138 &[&[MessagePattern::E, MessagePattern::EE]]
139 }
140 (InitiatorPattern::No, OneWayPattern::Known) => {
141 &[&[MessagePattern::E, MessagePattern::EE]]
142 }
143 (InitiatorPattern::No, OneWayPattern::Xmitted) => &[&[
144 MessagePattern::E,
145 MessagePattern::EE,
146 MessagePattern::S,
147 MessagePattern::ES,
148 ]],
149 (InitiatorPattern::Xmitted, OneWayPattern::No) => {
150 &[&[MessagePattern::E, MessagePattern::EE]]
151 }
152 (InitiatorPattern::Xmitted, OneWayPattern::Known) => {
153 &[&[MessagePattern::E, MessagePattern::EE]]
154 }
155 (InitiatorPattern::Xmitted, OneWayPattern::Xmitted) => &[&[
156 MessagePattern::E,
157 MessagePattern::EE,
158 MessagePattern::S,
159 MessagePattern::ES,
160 ]],
161 (InitiatorPattern::Known, OneWayPattern::No) => {
162 &[&[MessagePattern::E, MessagePattern::EE, MessagePattern::SE]]
163 }
164 (InitiatorPattern::Known, OneWayPattern::Known) => {
165 &[&[MessagePattern::E, MessagePattern::EE, MessagePattern::SE]]
166 }
167 (InitiatorPattern::Known, OneWayPattern::Xmitted) => &[&[
168 MessagePattern::E,
169 MessagePattern::EE,
170 MessagePattern::SE,
171 MessagePattern::S,
172 MessagePattern::ES,
173 ]],
174 (InitiatorPattern::Immediately, OneWayPattern::No) => {
175 &[&[MessagePattern::E, MessagePattern::EE, MessagePattern::SE]]
176 }
177 (InitiatorPattern::Immediately, OneWayPattern::Known) => {
178 &[&[MessagePattern::E, MessagePattern::EE, MessagePattern::SE]]
179 }
180 (InitiatorPattern::Immediately, OneWayPattern::Xmitted) => &[&[
181 MessagePattern::E,
182 MessagePattern::EE,
183 MessagePattern::SE,
184 MessagePattern::S,
185 MessagePattern::ES,
186 ]],
187 }
188 }
189 }
190}
191
192#[derive(Clone, Eq, PartialEq, Debug)]
193pub struct Keyset<E: Ecdh> {
194 pub e: E,
195 pub s: Option<E>,
196 pub re: Option<E::Pk>,
197 pub rs: Option<E::Pk>,
198}
199
200impl<E: Ecdh> Keyset<E> {
201 pub fn noise_nn() -> Self {
202 let pair = E::generate_keypair();
203 Self {
204 e: pair.0,
205 s: None,
206 re: None,
207 rs: None,
208 }
209 }
210
211 pub fn pre_message_key(&self, pmkp: PreMsgKeyPat, is_initiator: bool) -> Option<E::Pk> {
212 Some(match (pmkp, is_initiator) {
213 (PreMsgKeyPat::InitiatorStatic, true) | (PreMsgKeyPat::ResponderStatic, false) => {
214 self.expect_s().to_pk().expect("invalid static key")
215 }
216 (PreMsgKeyPat::ResponderStatic, true) | (PreMsgKeyPat::InitiatorStatic, false) => {
217 self.expect_rs().clone()
218 }
219 (PreMsgKeyPat::Empty, _) => return None,
220 })
221 }
222
223 pub fn expect_s(&self) -> &E { self.s.as_ref().expect("static key must be known") }
224
225 pub fn expect_re(&self) -> &E::Pk {
226 self.re.as_ref().expect("remote ephemeral key must be known at this stage")
227 }
228
229 pub fn expect_rs(&self) -> &E::Pk {
230 self.rs.as_ref().expect("remote static key must be known at this stage")
231 }
232}
233
234#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
235#[non_exhaustive] pub enum MessagePattern {
237 #[display("e")]
238 E,
239
240 #[display("s")]
241 S,
242
243 #[display("ee")]
244 EE,
245
246 #[display("es")]
247 ES,
248
249 #[display("se")]
250 SE,
251
252 #[display("ss")]
253 SS,
254 }