@@ -13,34 +13,73 @@ use std::sync::Arc;
1313use subtle:: ConstantTimeEq ;
1414use xoodoo:: Xoodyak ;
1515
16- /// Noise configuration struct.
17- #[ derive( Default ) ]
18- pub struct NoiseConfig {
19- /// Keypair to use. If none is provided one will be generated.
20- pub keypair : Option < Keypair > ,
16+ pub struct NoiseClientConfig {
17+ /// Keypair to use.
18+ pub keypair : Keypair ,
19+ /// Optional private shared key usable as a password for private networks.
20+ pub psk : Option < [ u8 ; 32 ] > ,
21+ /// Enables keylogging for debugging purposes to the path provided by `SSLKEYLOGFILE`.
22+ pub keylogger : Option < Arc < dyn KeyLog > > ,
2123 /// The remote public key. This needs to be set.
22- pub remote_public_key : Option < PublicKey > ,
24+ pub remote_public_key : PublicKey ,
25+ /// ALPN string to use.
26+ pub alpn : Vec < u8 > ,
27+ }
28+
29+ impl From < NoiseClientConfig > for NoiseConfig {
30+ fn from ( config : NoiseClientConfig ) -> Self {
31+ Self {
32+ keypair : Some ( config. keypair ) ,
33+ psk : config. psk ,
34+ keylogger : config. keylogger ,
35+ remote_public_key : Some ( config. remote_public_key ) ,
36+ alpn : Some ( config. alpn ) ,
37+ supported_protocols : None ,
38+ }
39+ }
40+ }
41+
42+ pub struct NoiseServerConfig {
43+ /// Keypair to use.
44+ pub keypair : Keypair ,
2345 /// Optional private shared key usable as a password for private networks.
2446 pub psk : Option < [ u8 ; 32 ] > ,
2547 /// Enables keylogging for debugging purposes to the path provided by `SSLKEYLOGFILE`.
2648 pub keylogger : Option < Arc < dyn KeyLog > > ,
49+ /// Supported ALPN identifiers.
50+ pub supported_protocols : Vec < Vec < u8 > > ,
2751}
2852
29- impl Clone for NoiseConfig {
30- fn clone ( & self ) -> Self {
31- let keypair = self
32- . keypair
33- . as_ref ( )
34- . map ( |keypair| Keypair :: from_bytes ( & keypair. to_bytes ( ) ) . unwrap ( ) ) ;
53+ impl From < NoiseServerConfig > for NoiseConfig {
54+ fn from ( config : NoiseServerConfig ) -> Self {
3555 Self {
36- keypair,
37- remote_public_key : self . remote_public_key ,
38- psk : self . psk ,
39- keylogger : self . keylogger . clone ( ) ,
56+ keypair : Some ( config. keypair ) ,
57+ psk : config. psk ,
58+ keylogger : config. keylogger ,
59+ remote_public_key : None ,
60+ alpn : None ,
61+ supported_protocols : Some ( config. supported_protocols ) ,
4062 }
4163 }
4264}
4365
66+ /// Noise configuration struct.
67+ #[ derive( Default ) ]
68+ pub struct NoiseConfig {
69+ /// Keypair to use.
70+ keypair : Option < Keypair > ,
71+ /// Optional private shared key usable as a password for private networks.
72+ psk : Option < [ u8 ; 32 ] > ,
73+ /// Enables keylogging for debugging purposes to the path provided by `SSLKEYLOGFILE`.
74+ keylogger : Option < Arc < dyn KeyLog > > ,
75+ /// The remote public key. This needs to be set.
76+ remote_public_key : Option < PublicKey > ,
77+ /// ALPN string to use.
78+ alpn : Option < Vec < u8 > > ,
79+ /// Supported ALPN identifiers.
80+ supported_protocols : Option < Vec < Vec < u8 > > > ,
81+ }
82+
4483impl ClientConfig < NoiseSession > for NoiseConfig {
4584 fn new ( ) -> Self {
4685 Default :: default ( )
@@ -81,6 +120,8 @@ impl NoiseConfig {
81120 e,
82121 s,
83122 psk : self . psk . unwrap_or_default ( ) ,
123+ alpn : self . alpn . clone ( ) ,
124+ supported_protocols : self . supported_protocols . clone ( ) ,
84125 transport_parameters : * params,
85126 remote_transport_parameters : None ,
86127 remote_e : None ,
@@ -91,13 +132,32 @@ impl NoiseConfig {
91132 }
92133}
93134
135+ impl Clone for NoiseConfig {
136+ fn clone ( & self ) -> Self {
137+ let keypair = self
138+ . keypair
139+ . as_ref ( )
140+ . map ( |keypair| Keypair :: from_bytes ( & keypair. to_bytes ( ) ) . unwrap ( ) ) ;
141+ Self {
142+ keypair,
143+ psk : self . psk ,
144+ keylogger : self . keylogger . clone ( ) ,
145+ remote_public_key : self . remote_public_key ,
146+ alpn : self . alpn . clone ( ) ,
147+ supported_protocols : self . supported_protocols . clone ( ) ,
148+ }
149+ }
150+ }
151+
94152pub struct NoiseSession {
95153 xoodyak : Xoodyak ,
96154 state : State ,
97155 side : Side ,
98156 e : Keypair ,
99157 s : Keypair ,
100158 psk : [ u8 ; 32 ] ,
159+ alpn : Option < Vec < u8 > > ,
160+ supported_protocols : Option < Vec < Vec < u8 > > > ,
101161 transport_parameters : TransportParameters ,
102162 remote_transport_parameters : Option < TransportParameters > ,
103163 remote_e : Option < PublicKey > ,
@@ -133,7 +193,7 @@ fn connection_refused(reason: &str) -> TransportError {
133193}
134194
135195impl Session for NoiseSession {
136- type HandshakeData = ( ) ;
196+ type HandshakeData = Vec < u8 > ;
137197 type Identity = PublicKey ;
138198 type ClientConfig = NoiseConfig ;
139199 type ServerConfig = Arc < NoiseConfig > ;
@@ -183,35 +243,84 @@ impl Session for NoiseSession {
183243 tracing:: trace!( "read_handshake {:?} {:?}" , self . state, self . side) ;
184244 match ( self . state , self . side ) {
185245 ( State :: Initial , Side :: Server ) => {
246+ // protocol identifier
247+ if handshake. is_empty ( ) {
248+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
249+ }
186250 let ( len, rest) = handshake. split_at ( 1 ) ;
187- let ( protocol_id, rest) = rest. split_at ( len[ 0 ] as usize ) ;
251+ let len = len[ 0 ] as usize ;
252+ if rest. len ( ) < len {
253+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
254+ }
255+ let ( protocol_id, rest) = rest. split_at ( len) ;
188256 if protocol_id != b"Noise_IKpsk1_Edx25519_ChaCha8Poly" {
189257 return Err ( connection_refused ( "unsupported protocol id" ) ) ;
190258 }
191- let ( e, rest) = rest. split_at ( 32 ) ;
192259 self . xoodyak . absorb ( protocol_id) ;
260+ // e
261+ if rest. len ( ) < 32 {
262+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
263+ }
264+ let ( e, rest) = rest. split_at ( 32 ) ;
193265 self . xoodyak . absorb ( e) ;
194- self . xoodyak . absorb ( self . s . public . as_bytes ( ) ) ;
195266 let e = PublicKey :: from_bytes ( e)
196267 . map_err ( |_| connection_refused ( "invalid ephemeral public key" ) ) ?;
197268 self . remote_e = Some ( e) ;
269+ // s
270+ self . xoodyak . absorb ( self . s . public . as_bytes ( ) ) ;
271+ // es
198272 let es = self . s . diffie_hellman ( & e) ;
199273 self . xoodyak . absorb ( & es) ;
274+ // initialize keyed session transcript
200275 let mut key = [ 0 ; 32 ] ;
201276 self . xoodyak . squeeze ( & mut key) ;
202277 self . xoodyak = Xoodyak :: keyed ( & key, None , None , None ) ;
278+ // s
279+ if rest. len ( ) < 32 {
280+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
281+ }
203282 let ( remote_s, rest) = rest. split_at ( 32 ) ;
204283 let mut s = [ 0 ; 32 ] ;
205284 self . xoodyak . decrypt ( & remote_s, & mut s) ;
206285 let s = PublicKey :: from_bytes ( & s)
207286 . map_err ( |_| connection_refused ( "invalid static public key" ) ) ?;
208287 self . remote_s = Some ( s) ;
288+ // ss
209289 let ss = self . s . diffie_hellman ( & s) ;
210290 self . xoodyak . absorb ( & ss) ;
291+ // psk
211292 self . xoodyak . absorb ( & self . psk ) ;
293+ // alpn
294+ if rest. is_empty ( ) {
295+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
296+ }
297+ let ( len, rest) = rest. split_at ( 1 ) ;
298+ let len = len[ 0 ] as usize ;
299+ if rest. len ( ) < len {
300+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
301+ }
302+ let ( alpn, rest) = rest. split_at ( len) ;
303+ let mut alpn = alpn. to_vec ( ) ;
304+ self . xoodyak . decrypt_in_place ( & mut alpn) ;
305+ let is_supported = self
306+ . supported_protocols
307+ . as_ref ( )
308+ . expect ( "invalid config" )
309+ . into_iter ( )
310+ . find ( |proto| proto. as_slice ( ) == alpn)
311+ . is_some ( ) ;
312+ if !is_supported {
313+ return Err ( connection_refused ( "unsupported alpn" ) ) ;
314+ }
315+ self . alpn = Some ( alpn) ;
316+ // transport parameters
317+ if rest. len ( ) < 16 {
318+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
319+ }
212320 let ( params, auth) = rest. split_at ( rest. len ( ) - 16 ) ;
213321 let mut transport_parameters = vec ! [ 0 ; params. len( ) ] ;
214322 self . xoodyak . decrypt ( & params, & mut transport_parameters) ;
323+ // check tag
215324 let mut tag = [ 0 ; 16 ] ;
216325 self . xoodyak . squeeze ( & mut tag) ;
217326 if !bool:: from ( tag. ct_eq ( & auth) ) {
@@ -225,19 +334,30 @@ impl Session for NoiseSession {
225334 Ok ( true )
226335 }
227336 ( State :: Handshake , Side :: Client ) => {
337+ // e
338+ if handshake. len ( ) < 32 {
339+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
340+ }
228341 let ( remote_e, rest) = handshake. split_at ( 32 ) ;
229342 let mut e = [ 0 ; 32 ] ;
230343 self . xoodyak . decrypt ( & remote_e, & mut e) ;
231344 let e = PublicKey :: from_bytes ( & e)
232345 . map_err ( |_| connection_refused ( "invalid ephemeral public key" ) ) ?;
233346 self . remote_e = Some ( e) ;
347+ // ee
234348 let ee = self . e . diffie_hellman ( & e) ;
235349 self . xoodyak . absorb ( & ee) ;
350+ // se
236351 let se = self . s . diffie_hellman ( & e) ;
237352 self . xoodyak . absorb ( & se) ;
353+ // transport parameters
354+ if rest. len ( ) < 16 {
355+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
356+ }
238357 let ( params, auth) = rest. split_at ( rest. len ( ) - 16 ) ;
239358 let mut transport_parameters = vec ! [ 0 ; params. len( ) ] ;
240359 self . xoodyak . decrypt ( & params, & mut transport_parameters) ;
360+ // check tag
241361 let mut tag = [ 0 ; 16 ] ;
242362 self . xoodyak . squeeze ( & mut tag) ;
243363 if !bool:: from ( tag. ct_eq ( & auth) ) {
@@ -262,34 +382,50 @@ impl Session for NoiseSession {
262382 tracing:: trace!( "write_handshake {:?} {:?}" , self . state, self . side) ;
263383 match ( self . state , self . side ) {
264384 ( State :: Initial , Side :: Client ) => {
385+ // protocol identifier
265386 let protocol_id = b"Noise_IKpsk1_Edx25519_ChaCha8Poly" ;
266387 self . xoodyak . absorb ( protocol_id) ;
267388 handshake. extend_from_slice ( & [ protocol_id. len ( ) as u8 ] ) ;
268389 handshake. extend_from_slice ( protocol_id) ;
390+ // e
269391 self . xoodyak . absorb ( self . e . public . as_bytes ( ) ) ;
270392 handshake. extend_from_slice ( self . e . public . as_bytes ( ) ) ;
393+ // s
271394 let s = self . remote_s . unwrap ( ) ;
272395 self . xoodyak . absorb ( s. as_bytes ( ) ) ;
396+ // es
273397 let es = self . e . diffie_hellman ( & s) ;
274398 self . xoodyak . absorb ( & es) ;
399+ // initialize keyed session transcript
275400 let mut key = [ 0 ; 32 ] ;
276401 self . xoodyak . squeeze ( & mut key) ;
277402 self . xoodyak = Xoodyak :: keyed ( & key, None , None , None ) ;
278- self . state = State :: Handshake ;
403+ // s
279404 let mut s = [ 0 ; 32 ] ;
280405 self . xoodyak . encrypt ( self . s . public . as_bytes ( ) , & mut s) ;
281406 handshake. extend_from_slice ( & s) ;
407+ // ss
282408 let s = self . remote_s . unwrap ( ) ;
283409 let ss = self . s . diffie_hellman ( & s) ;
284410 self . xoodyak . absorb ( & ss) ;
411+ // psk
285412 self . xoodyak . absorb ( & self . psk ) ;
413+ // alpn
414+ let alpn = self . alpn . as_ref ( ) . expect ( "invalid config" ) ;
415+ handshake. extend_from_slice ( & [ alpn. len ( ) as u8 ] ) ;
416+ let pos = handshake. len ( ) ;
417+ handshake. extend_from_slice ( alpn) ;
418+ self . xoodyak . encrypt_in_place ( & mut handshake[ pos..] ) ;
419+ // transport parameters
286420 let mut transport_parameters = vec ! [ ] ;
287421 self . transport_parameters . write ( & mut transport_parameters) ;
288422 self . xoodyak . encrypt_in_place ( & mut transport_parameters) ;
289423 handshake. extend_from_slice ( & transport_parameters) ;
424+ // tag
290425 let mut tag = [ 0 ; 16 ] ;
291426 self . xoodyak . squeeze ( & mut tag) ;
292427 handshake. extend_from_slice ( & tag) ;
428+ // 0-rtt
293429 self . state = State :: ZeroRtt ;
294430 None
295431 }
@@ -303,20 +439,26 @@ impl Session for NoiseSession {
303439 } )
304440 }
305441 ( State :: Handshake , Side :: Server ) => {
442+ // e
306443 let mut e = [ 0 ; 32 ] ;
307444 self . xoodyak . encrypt ( self . e . public . as_bytes ( ) , & mut e) ;
308445 handshake. extend_from_slice ( & e) ;
446+ // ee
309447 let ee = self . e . diffie_hellman ( & self . remote_e . unwrap ( ) ) ;
310448 self . xoodyak . absorb ( & ee) ;
449+ // se
311450 let se = self . e . diffie_hellman ( & self . remote_s . unwrap ( ) ) ;
312451 self . xoodyak . absorb ( & se) ;
452+ // transport parameters
313453 let mut transport_parameters = vec ! [ ] ;
314454 self . transport_parameters . write ( & mut transport_parameters) ;
315455 self . xoodyak . encrypt_in_place ( & mut transport_parameters) ;
316456 handshake. extend_from_slice ( & transport_parameters) ;
457+ // tag
317458 let mut tag = [ 0 ; 16 ] ;
318459 self . xoodyak . squeeze ( & mut tag) ;
319460 handshake. extend_from_slice ( & tag) ;
461+ // 1-rtt keys
320462 let packet = self . next_1rtt_keys ( ) ;
321463 self . state = State :: Data ;
322464 Some ( Keys {
@@ -353,7 +495,7 @@ impl Session for NoiseSession {
353495 }
354496
355497 fn handshake_data ( & self ) -> Option < Self :: HandshakeData > {
356- Some ( ( ) )
498+ self . alpn . clone ( )
357499 }
358500
359501 fn export_keying_material (
0 commit comments