@@ -13,34 +13,73 @@ use std::sync::Arc;
13
13
use subtle:: ConstantTimeEq ;
14
14
use xoodoo:: Xoodyak ;
15
15
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 > > ,
21
23
/// 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 ,
23
45
/// Optional private shared key usable as a password for private networks.
24
46
pub psk : Option < [ u8 ; 32 ] > ,
25
47
/// Enables keylogging for debugging purposes to the path provided by `SSLKEYLOGFILE`.
26
48
pub keylogger : Option < Arc < dyn KeyLog > > ,
49
+ /// Supported ALPN identifiers.
50
+ pub supported_protocols : Vec < Vec < u8 > > ,
27
51
}
28
52
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 {
35
55
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 ) ,
40
62
}
41
63
}
42
64
}
43
65
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
+
44
83
impl ClientConfig < NoiseSession > for NoiseConfig {
45
84
fn new ( ) -> Self {
46
85
Default :: default ( )
@@ -81,6 +120,8 @@ impl NoiseConfig {
81
120
e,
82
121
s,
83
122
psk : self . psk . unwrap_or_default ( ) ,
123
+ alpn : self . alpn . clone ( ) ,
124
+ supported_protocols : self . supported_protocols . clone ( ) ,
84
125
transport_parameters : * params,
85
126
remote_transport_parameters : None ,
86
127
remote_e : None ,
@@ -91,13 +132,32 @@ impl NoiseConfig {
91
132
}
92
133
}
93
134
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
+
94
152
pub struct NoiseSession {
95
153
xoodyak : Xoodyak ,
96
154
state : State ,
97
155
side : Side ,
98
156
e : Keypair ,
99
157
s : Keypair ,
100
158
psk : [ u8 ; 32 ] ,
159
+ alpn : Option < Vec < u8 > > ,
160
+ supported_protocols : Option < Vec < Vec < u8 > > > ,
101
161
transport_parameters : TransportParameters ,
102
162
remote_transport_parameters : Option < TransportParameters > ,
103
163
remote_e : Option < PublicKey > ,
@@ -133,7 +193,7 @@ fn connection_refused(reason: &str) -> TransportError {
133
193
}
134
194
135
195
impl Session for NoiseSession {
136
- type HandshakeData = ( ) ;
196
+ type HandshakeData = Vec < u8 > ;
137
197
type Identity = PublicKey ;
138
198
type ClientConfig = NoiseConfig ;
139
199
type ServerConfig = Arc < NoiseConfig > ;
@@ -183,35 +243,84 @@ impl Session for NoiseSession {
183
243
tracing:: trace!( "read_handshake {:?} {:?}" , self . state, self . side) ;
184
244
match ( self . state , self . side ) {
185
245
( State :: Initial , Side :: Server ) => {
246
+ // protocol identifier
247
+ if handshake. is_empty ( ) {
248
+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
249
+ }
186
250
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) ;
188
256
if protocol_id != b"Noise_IKpsk1_Edx25519_ChaCha8Poly" {
189
257
return Err ( connection_refused ( "unsupported protocol id" ) ) ;
190
258
}
191
- let ( e, rest) = rest. split_at ( 32 ) ;
192
259
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 ) ;
193
265
self . xoodyak . absorb ( e) ;
194
- self . xoodyak . absorb ( self . s . public . as_bytes ( ) ) ;
195
266
let e = PublicKey :: from_bytes ( e)
196
267
. map_err ( |_| connection_refused ( "invalid ephemeral public key" ) ) ?;
197
268
self . remote_e = Some ( e) ;
269
+ // s
270
+ self . xoodyak . absorb ( self . s . public . as_bytes ( ) ) ;
271
+ // es
198
272
let es = self . s . diffie_hellman ( & e) ;
199
273
self . xoodyak . absorb ( & es) ;
274
+ // initialize keyed session transcript
200
275
let mut key = [ 0 ; 32 ] ;
201
276
self . xoodyak . squeeze ( & mut key) ;
202
277
self . xoodyak = Xoodyak :: keyed ( & key, None , None , None ) ;
278
+ // s
279
+ if rest. len ( ) < 32 {
280
+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
281
+ }
203
282
let ( remote_s, rest) = rest. split_at ( 32 ) ;
204
283
let mut s = [ 0 ; 32 ] ;
205
284
self . xoodyak . decrypt ( & remote_s, & mut s) ;
206
285
let s = PublicKey :: from_bytes ( & s)
207
286
. map_err ( |_| connection_refused ( "invalid static public key" ) ) ?;
208
287
self . remote_s = Some ( s) ;
288
+ // ss
209
289
let ss = self . s . diffie_hellman ( & s) ;
210
290
self . xoodyak . absorb ( & ss) ;
291
+ // psk
211
292
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
+ }
212
320
let ( params, auth) = rest. split_at ( rest. len ( ) - 16 ) ;
213
321
let mut transport_parameters = vec ! [ 0 ; params. len( ) ] ;
214
322
self . xoodyak . decrypt ( & params, & mut transport_parameters) ;
323
+ // check tag
215
324
let mut tag = [ 0 ; 16 ] ;
216
325
self . xoodyak . squeeze ( & mut tag) ;
217
326
if !bool:: from ( tag. ct_eq ( & auth) ) {
@@ -225,19 +334,30 @@ impl Session for NoiseSession {
225
334
Ok ( true )
226
335
}
227
336
( State :: Handshake , Side :: Client ) => {
337
+ // e
338
+ if handshake. len ( ) < 32 {
339
+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
340
+ }
228
341
let ( remote_e, rest) = handshake. split_at ( 32 ) ;
229
342
let mut e = [ 0 ; 32 ] ;
230
343
self . xoodyak . decrypt ( & remote_e, & mut e) ;
231
344
let e = PublicKey :: from_bytes ( & e)
232
345
. map_err ( |_| connection_refused ( "invalid ephemeral public key" ) ) ?;
233
346
self . remote_e = Some ( e) ;
347
+ // ee
234
348
let ee = self . e . diffie_hellman ( & e) ;
235
349
self . xoodyak . absorb ( & ee) ;
350
+ // se
236
351
let se = self . s . diffie_hellman ( & e) ;
237
352
self . xoodyak . absorb ( & se) ;
353
+ // transport parameters
354
+ if rest. len ( ) < 16 {
355
+ return Err ( connection_refused ( "invalid crypto frame" ) ) ;
356
+ }
238
357
let ( params, auth) = rest. split_at ( rest. len ( ) - 16 ) ;
239
358
let mut transport_parameters = vec ! [ 0 ; params. len( ) ] ;
240
359
self . xoodyak . decrypt ( & params, & mut transport_parameters) ;
360
+ // check tag
241
361
let mut tag = [ 0 ; 16 ] ;
242
362
self . xoodyak . squeeze ( & mut tag) ;
243
363
if !bool:: from ( tag. ct_eq ( & auth) ) {
@@ -262,34 +382,50 @@ impl Session for NoiseSession {
262
382
tracing:: trace!( "write_handshake {:?} {:?}" , self . state, self . side) ;
263
383
match ( self . state , self . side ) {
264
384
( State :: Initial , Side :: Client ) => {
385
+ // protocol identifier
265
386
let protocol_id = b"Noise_IKpsk1_Edx25519_ChaCha8Poly" ;
266
387
self . xoodyak . absorb ( protocol_id) ;
267
388
handshake. extend_from_slice ( & [ protocol_id. len ( ) as u8 ] ) ;
268
389
handshake. extend_from_slice ( protocol_id) ;
390
+ // e
269
391
self . xoodyak . absorb ( self . e . public . as_bytes ( ) ) ;
270
392
handshake. extend_from_slice ( self . e . public . as_bytes ( ) ) ;
393
+ // s
271
394
let s = self . remote_s . unwrap ( ) ;
272
395
self . xoodyak . absorb ( s. as_bytes ( ) ) ;
396
+ // es
273
397
let es = self . e . diffie_hellman ( & s) ;
274
398
self . xoodyak . absorb ( & es) ;
399
+ // initialize keyed session transcript
275
400
let mut key = [ 0 ; 32 ] ;
276
401
self . xoodyak . squeeze ( & mut key) ;
277
402
self . xoodyak = Xoodyak :: keyed ( & key, None , None , None ) ;
278
- self . state = State :: Handshake ;
403
+ // s
279
404
let mut s = [ 0 ; 32 ] ;
280
405
self . xoodyak . encrypt ( self . s . public . as_bytes ( ) , & mut s) ;
281
406
handshake. extend_from_slice ( & s) ;
407
+ // ss
282
408
let s = self . remote_s . unwrap ( ) ;
283
409
let ss = self . s . diffie_hellman ( & s) ;
284
410
self . xoodyak . absorb ( & ss) ;
411
+ // psk
285
412
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
286
420
let mut transport_parameters = vec ! [ ] ;
287
421
self . transport_parameters . write ( & mut transport_parameters) ;
288
422
self . xoodyak . encrypt_in_place ( & mut transport_parameters) ;
289
423
handshake. extend_from_slice ( & transport_parameters) ;
424
+ // tag
290
425
let mut tag = [ 0 ; 16 ] ;
291
426
self . xoodyak . squeeze ( & mut tag) ;
292
427
handshake. extend_from_slice ( & tag) ;
428
+ // 0-rtt
293
429
self . state = State :: ZeroRtt ;
294
430
None
295
431
}
@@ -303,20 +439,26 @@ impl Session for NoiseSession {
303
439
} )
304
440
}
305
441
( State :: Handshake , Side :: Server ) => {
442
+ // e
306
443
let mut e = [ 0 ; 32 ] ;
307
444
self . xoodyak . encrypt ( self . e . public . as_bytes ( ) , & mut e) ;
308
445
handshake. extend_from_slice ( & e) ;
446
+ // ee
309
447
let ee = self . e . diffie_hellman ( & self . remote_e . unwrap ( ) ) ;
310
448
self . xoodyak . absorb ( & ee) ;
449
+ // se
311
450
let se = self . e . diffie_hellman ( & self . remote_s . unwrap ( ) ) ;
312
451
self . xoodyak . absorb ( & se) ;
452
+ // transport parameters
313
453
let mut transport_parameters = vec ! [ ] ;
314
454
self . transport_parameters . write ( & mut transport_parameters) ;
315
455
self . xoodyak . encrypt_in_place ( & mut transport_parameters) ;
316
456
handshake. extend_from_slice ( & transport_parameters) ;
457
+ // tag
317
458
let mut tag = [ 0 ; 16 ] ;
318
459
self . xoodyak . squeeze ( & mut tag) ;
319
460
handshake. extend_from_slice ( & tag) ;
461
+ // 1-rtt keys
320
462
let packet = self . next_1rtt_keys ( ) ;
321
463
self . state = State :: Data ;
322
464
Some ( Keys {
@@ -353,7 +495,7 @@ impl Session for NoiseSession {
353
495
}
354
496
355
497
fn handshake_data ( & self ) -> Option < Self :: HandshakeData > {
356
- Some ( ( ) )
498
+ self . alpn . clone ( )
357
499
}
358
500
359
501
fn export_keying_material (
0 commit comments