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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2019 ifak e.V. Magdeburg (Holger Zipper)
* Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil)
*/
/**
* PubSubKeyStorage
* ================
* A PubSubKeyStorage provides a linked list to store all the keys used to
* secure the messages. It keeps the records of old keys (past keys), current
* key, new keys (futurekeys), time to move to next key and callback id.
*
* PubSubKeyListItem is the basic item stored in the KeyList of KeyStorage. It
* provides keyId, Key, and pointer to the next key in KeyList. The KeyId is used
* to identify and update currentKey in the keystorage. The KeyId is the SecurityTokenId
* that appears in the header of messages secured with the CurrentKey.
*
* Working
* =======
* +------------------------------+
* |AddReaderGroup/AddWriterGroup |
* +------------------------------+
* |
* V
* +--------------------+
* |CheckSecurityGroupId|
* +--------------------+
* |Yes
* V
* +--------------------+
* |InitializeKeyStorage|
* +--------------------+
* |
* V
* +----------------------------+
* |store/updateKeysInKeyStorage|
* +----------------------------+
* |
* V
* +------------------------------------------+
* |activateKeysToAllPubSubGroupChannelContext|
* +------------------------------------------+
* | Ʌ
* V |
* +-----------------------+ |
* |addKeyRolloverCallbacks| |
* +-----------------------+ |
* | |
* V |
* +-------------------+ |
* |keyRolloverCallback| |
* +-------------------+ |
* |CurrentKey!=LastItem |
* -------------------------+
*
* A KeyStorage is created and initialized when a ReaderGroup or WriterGroup is
* created with securityGroupId and SecurityMode SignAndEncrypt. The new
* KeyStorage is added to the server KeyStorageList. At this time KeyList is empty.
*
* UA_PubSubKeyStorage_storeSecurityKeys is used to push the keys into existing
* keystorage. In order to update the KeyList of an existing keyStorage,
* UA_PubSubKeyStorage_update is called.
*
* After adding/updating the keys to keystorage, the current key should be
* activated to the associated PubSub Group's ChannelContext in the server. The
* security Policy associated with PubSub Group will take the keys from
* channel context and use them to secure the messages.
* The UA_PubSubKeyStorage_storeSecurityKeys and UA_PubSubKeyStorage_update
* method will be used by setSecurityKeysAction and getSecurityKeysAction to
* retrieve the keys from SKS server and store keys in local storage.
*
* Each key has a life time, after which the current key is expired and move to
* next key in the existing list. For this a callback function is added to the
* server. The callback function keyRolloverCallback is added to the server as a
* timed callback. The addKeyRolloverCallbacks function calculates the time
* stamp to trigger the callback when the current Key expires and roll
* over to the next key in existing list.
*
*/
/**
* @brief This structure holds the information about the keys
*/
typedef struct UA_PubSubKeyListItem UA_PubSubKeyListItem;
/* Queue Definition*/
typedef keyListItems;
/* Used to hold configuration information required to connect an SKS server and
* fetch the security keys */
typedef struct UA_PubSubSKSConfig UA_PubSubSKSConfig;
/* Holds all info and keys related to one SecurityGroup */
;
/**
* @brief Find the Keystorage from the KeyStorageList and returns the pointer to
* the keystorage
*
* @param psm holds the keystoragelist
* @param securityGroupId of the keystorage to be found
* @return Pointer to the keystorage on success, null pointer on failure
*/
UA_PubSubKeyStorage *
;
/**
* @brief retreives the security policy pointer from the PubSub configuration by
* SecurityPolicyUri
*
* @param psm the PubSubManager
* @param securityPolicyUri the URI of the security policy
* @param policy the pointer to the security policy
* @return UA_StatusCode return status code
*/
UA_PubSubSecurityPolicy *
;
/**
* @brief Deletes the keystorage from the server and its members
*
* @param psm the PubSubManager
* @param keyStorage pointer to the keystorage
*/
void
;
/**
* @brief Initializes an empty Keystorage for the SecurityGroupId and add it to the Server
* KeyStorageList
*
* @param psm the PubSubManager
* @param keyStorage Pointer to the keystorage to be initialized
* @param securityGroupId The identifier of the SecurityGroup
* @param policy The security policy assocaited with the security algorithm
* @param maxPastKeyCount maximum number of past keys a keystorage is allowed to store
* @param maxFutureKeyCount maximum number of future keys a keystorage is allowed to store
* @return UA_StatusCode return status code
*/
UA_StatusCode
;
void
;
/**
* @brief Add keys tot the key storage. Generates the keyId internally. They get
* appended to the end of the list. This method DOES NOT VALIDATE the
* maxKeyListSize property! Do this before.
*
* @param keyStorage pointer to the keyStorage
* @param keysSize the number of keys provided
* @param keys pointer to the keys
* @param currentKeyId The new keyIds start at currentKeyId + 1
* @return UA_StatusCode the return status
*/
UA_StatusCode
;
/* Fetch the key from the list and set it as the current key */
UA_StatusCode
;
/**
* @brief Finds the KeyItem from the KeyList by KeyId
*
* @param keyStorage pointer to the keystorage
* @param keyId the identifier of the Key
* @return NULL or the found item
*/
UA_PubSubKeyListItem *
;
/**
* @brief Adds a new KeyItem at the end of the KeyList
* to the new KeyListItem.
*
* @param keyStorage pointer to the keystorage
* @param key the key to be added
* @param keyID the keyID associated with the key to be added
*/
UA_PubSubKeyListItem *
;
/**
* @brief It calculates the time to trigger the callback to update current key, adds the
* callback to the server and returns the callbackId.
*
* @param psm the PubSubManager
* @param keyStorage the pointer to the existing keystorage in the server
* @param callback the callback function to be added to the server
* @param timeToNextMs time in milli seconds to trigger the callback function
* @param callbackID the returned callbackId of the added callback function
* @return UA_StatusCode the return status
*/
UA_StatusCode
;
/**
* @brief It takes the current Key data, divide it into signing key, encrypting key and
* keyNonce according to security policy associated with PubSub Group and set it in
* channel context of the assocaited PubSub Group. In case of pubSubGroupId is
* UA_NODEID_NULL, all the Reader/WriterGroup's channelcontext are updated with matching
* SecurityGroupId.
*
* @param psm the PubSubManager
* @param pubSubGroupId the nodeId of the Reader/WirterGroup whose channel context to be
* updated
* @param securityGroupId The identifier for the SecurityGroup
* @return UA_StatusCode return status code
*/
UA_StatusCode
;
/**
* @brief The callback function to update the current key from keystorage in the server
* and activate the current key into channel context of the associated PubSub Group
*
* @param psm the PubSubManager
* @param keyStorage the pointer to the keystorage
*/
void
;
/* KeyStorage must be referenced by atleast one PubSubGroup. This method reduces
* the reference count by one. If no PubSubGroup uses the key storage, then it
* is deleted. */
void
;
/* Calls get SecurityKeys Method and Store the returned keys into KeyStorage */
UA_StatusCode
;
/* UA_ENABLE_PUBSUB */