3
3
// Copyright (C) 2017-2024 Adam Lock
4
4
5
5
use std:: {
6
+ collections:: HashMap ,
6
7
io:: { Cursor , Write } ,
7
8
ops:: Range ,
8
9
sync:: Arc ,
9
10
} ;
10
11
11
- use chrono:: { Duration , TimeDelta } ;
12
+ use chrono:: Duration ;
12
13
13
14
use crate :: crypto:: {
14
15
aeskey:: AesKey ,
@@ -35,6 +36,12 @@ pub enum Role {
35
36
Server ,
36
37
}
37
38
39
+ #[ derive( Debug ) ]
40
+ struct RemoteKeys {
41
+ keys : ( Vec < u8 > , AesKey , Vec < u8 > ) ,
42
+ expires_at : DateTime ,
43
+ }
44
+
38
45
/// Holds all of the security information related to this session
39
46
#[ derive( Debug ) ]
40
47
pub struct SecureChannel {
@@ -63,7 +70,14 @@ pub struct SecureChannel {
63
70
/// Our nonce generated while handling open secure channel
64
71
local_nonce : Vec < u8 > ,
65
72
/// Client (i.e. other end's set of keys) Symmetric Signing Key, Encrypt Key, IV
66
- remote_keys : Option < ( Vec < u8 > , AesKey , Vec < u8 > ) > ,
73
+ ///
74
+ /// This is a map of channel token ids and their respective keys. We need to keep
75
+ /// the old keys around as the client should accept messages secured by an expired
76
+ /// SecurityToken for up to 25 % of the token lifetime.
77
+ ///
78
+ /// See the "OpenSecureChannel" section in the spec for more info:
79
+ /// https://reference.opcfoundation.org/Core/Part4/v105/docs/5.5.2
80
+ remote_keys : HashMap < u32 , RemoteKeys > ,
67
81
/// Server (i.e. our end's set of keys) Symmetric Signing Key, Decrypt Key, IV
68
82
local_keys : Option < ( Vec < u8 > , AesKey , Vec < u8 > ) > ,
69
83
/// Decoding options
@@ -88,7 +102,7 @@ impl SecureChannel {
88
102
private_key : None ,
89
103
remote_cert : None ,
90
104
local_keys : None ,
91
- remote_keys : None ,
105
+ remote_keys : HashMap :: new ( ) ,
92
106
decoding_options : DecodingOptions :: default ( ) ,
93
107
}
94
108
}
@@ -121,7 +135,7 @@ impl SecureChannel {
121
135
private_key,
122
136
remote_cert : None ,
123
137
local_keys : None ,
124
- remote_keys : None ,
138
+ remote_keys : HashMap :: new ( ) ,
125
139
decoding_options,
126
140
}
127
141
}
@@ -226,10 +240,10 @@ impl SecureChannel {
226
240
false
227
241
} else {
228
242
// Check if secure channel 75% close to expiration in which case send a renew
229
- let renew_lifetime = ( self . token_lifetime ( ) * 3 ) / 4 ;
230
- let renew_lifetime = TimeDelta :: try_milliseconds ( renew_lifetime as i64 ) . unwrap ( ) ;
243
+ let renew_lifetime = ( self . token_lifetime * 3 ) / 4 ;
244
+ let renew_lifetime = Duration :: milliseconds ( renew_lifetime as i64 ) ;
231
245
// Renew the token?
232
- DateTime :: now ( ) - self . token_created_at ( ) > renew_lifetime
246
+ DateTime :: now ( ) - self . token_created_at > renew_lifetime
233
247
}
234
248
}
235
249
@@ -356,7 +370,7 @@ impl SecureChannel {
356
370
/// are used to secure Messages sent by the Server.
357
371
///
358
372
pub fn derive_keys ( & mut self ) {
359
- self . remote_keys = Some (
373
+ self . insert_remote_keys (
360
374
self . security_policy
361
375
. make_secure_channel_keys ( & self . local_nonce , & self . remote_nonce ) ,
362
376
) ;
@@ -366,16 +380,16 @@ impl SecureChannel {
366
380
) ;
367
381
trace ! ( "Remote nonce = {:?}" , self . remote_nonce) ;
368
382
trace ! ( "Local nonce = {:?}" , self . local_nonce) ;
369
- trace ! ( "Derived remote keys = {:?}" , self . remote_keys) ;
383
+ trace ! (
384
+ "Derived remote keys = {:?}" ,
385
+ self . get_remote_keys( self . token_id)
386
+ ) ;
370
387
trace ! ( "Derived local keys = {:?}" , self . local_keys) ;
371
388
}
372
389
373
390
/// Test if the token has expired yet
374
391
pub fn token_has_expired ( & self ) -> bool {
375
- let token_created_at = self . token_created_at ;
376
- let token_expires =
377
- token_created_at + TimeDelta :: try_seconds ( self . token_lifetime as i64 ) . unwrap ( ) ;
378
- DateTime :: now ( ) . ge ( & token_expires)
392
+ DateTime :: now ( ) >= self . token_created_at + Duration :: seconds ( self . token_lifetime as i64 )
379
393
}
380
394
381
395
/// Calculates the signature size for a message depending on the supplied security header
@@ -739,11 +753,20 @@ impl SecureChannel {
739
753
encrypted_range
740
754
) ;
741
755
756
+ let SecurityHeader :: Symmetric ( security_header) = security_header else {
757
+ error ! (
758
+ "Expected symmetric security header, got {:?}" ,
759
+ security_header
760
+ ) ;
761
+ return Err ( StatusCode :: BadUnexpectedError ) ;
762
+ } ;
763
+
742
764
let mut decrypted_data = vec ! [ 0u8 ; message_size] ;
743
765
let decrypted_size = self . symmetric_decrypt_and_verify (
744
766
src,
745
767
signed_range,
746
768
encrypted_range,
769
+ security_header. token_id ,
747
770
& mut decrypted_data,
748
771
) ?;
749
772
@@ -1048,8 +1071,32 @@ impl SecureChannel {
1048
1071
self . local_keys . as_ref ( ) . unwrap ( )
1049
1072
}
1050
1073
1051
- fn remote_keys ( & self ) -> & ( Vec < u8 > , AesKey , Vec < u8 > ) {
1052
- self . remote_keys . as_ref ( ) . unwrap ( )
1074
+ fn insert_remote_keys ( & mut self , keys : ( Vec < u8 > , AesKey , Vec < u8 > ) ) {
1075
+ let expires_at = ( self . token_lifetime as f32 * 1.25 ) . ceil ( ) ;
1076
+ let expires_at = Duration :: milliseconds ( expires_at as i64 ) ;
1077
+
1078
+ // Insert the remote keys.
1079
+ self . remote_keys . insert (
1080
+ self . token_id ,
1081
+ RemoteKeys {
1082
+ keys,
1083
+ expires_at : self . token_created_at + expires_at,
1084
+ } ,
1085
+ ) ;
1086
+
1087
+ // Remove any expired keys.
1088
+ self . remote_keys
1089
+ . retain ( |_, v| DateTime :: now ( ) < v. expires_at ) ;
1090
+ }
1091
+
1092
+ fn get_remote_keys ( & self , token_id : u32 ) -> Result < & ( Vec < u8 > , AesKey , Vec < u8 > ) , StatusCode > {
1093
+ match self . remote_keys . get ( & token_id) {
1094
+ Some ( remote_keys) => Ok ( & remote_keys. keys ) ,
1095
+ None => {
1096
+ error ! ( "No remote keys found for token: {}" , token_id) ;
1097
+ Err ( StatusCode :: BadUnexpectedError )
1098
+ }
1099
+ }
1053
1100
}
1054
1101
1055
1102
fn encryption_keys ( & self ) -> ( & AesKey , & [ u8 ] ) {
@@ -1061,13 +1108,13 @@ impl SecureChannel {
1061
1108
& ( self . local_keys ( ) ) . 0
1062
1109
}
1063
1110
1064
- fn decryption_keys ( & self ) -> ( & AesKey , & [ u8 ] ) {
1065
- let keys = self . remote_keys ( ) ;
1066
- ( & keys. 1 , & keys. 2 )
1111
+ fn decryption_keys ( & self , token_id : u32 ) -> Result < ( & AesKey , & [ u8 ] ) , StatusCode > {
1112
+ let keys = self . get_remote_keys ( token_id ) ? ;
1113
+ Ok ( ( & keys. 1 , & keys. 2 ) )
1067
1114
}
1068
1115
1069
- fn verification_key ( & self ) -> & [ u8 ] {
1070
- & ( self . remote_keys ( ) ) . 0
1116
+ fn verification_key ( & self , token_id : u32 ) -> Result < & [ u8 ] , StatusCode > {
1117
+ Ok ( & ( self . get_remote_keys ( token_id ) ) ? . 0 )
1071
1118
}
1072
1119
1073
1120
/// Encode data using security. Destination buffer is expected to be same size as src and expected
@@ -1178,6 +1225,7 @@ impl SecureChannel {
1178
1225
src : & [ u8 ] ,
1179
1226
signed_range : Range < usize > ,
1180
1227
encrypted_range : Range < usize > ,
1228
+ token_id : u32 ,
1181
1229
dst : & mut [ u8 ] ,
1182
1230
) -> Result < usize , StatusCode > {
1183
1231
match self . security_mode {
@@ -1198,7 +1246,7 @@ impl SecureChannel {
1198
1246
signed_range,
1199
1247
signed_range. end
1200
1248
) ;
1201
- let verification_key = self . verification_key ( ) ;
1249
+ let verification_key = self . verification_key ( token_id ) ? ;
1202
1250
self . security_policy . symmetric_verify_signature (
1203
1251
verification_key,
1204
1252
& dst[ signed_range. clone ( ) ] ,
@@ -1222,7 +1270,7 @@ impl SecureChannel {
1222
1270
1223
1271
// Decrypt encrypted portion
1224
1272
let mut decrypted_tmp = vec ! [ 0u8 ; ciphertext_size + 16 ] ; // tmp includes +16 for blocksize
1225
- let ( key, iv) = self . decryption_keys ( ) ;
1273
+ let ( key, iv) = self . decryption_keys ( token_id ) ? ;
1226
1274
1227
1275
trace ! (
1228
1276
"Secure decrypt called with encrypted range {:?}" ,
@@ -1250,7 +1298,7 @@ impl SecureChannel {
1250
1298
signed_range,
1251
1299
signature_range
1252
1300
) ;
1253
- let verification_key = self . verification_key ( ) ;
1301
+ let verification_key = self . verification_key ( token_id ) ? ;
1254
1302
self . security_policy . symmetric_verify_signature (
1255
1303
verification_key,
1256
1304
& dst[ signed_range] ,
0 commit comments