/src/S2OPC/src/PubSub/security/sopc_pubsub_sks.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Licensed to Systerel under one or more contributor license |
3 | | * agreements. See the NOTICE file distributed with this work |
4 | | * for additional information regarding copyright ownership. |
5 | | * Systerel licenses this file to you under the Apache |
6 | | * License, Version 2.0 (the "License"); you may not use this |
7 | | * file except in compliance with the License. You may obtain |
8 | | * a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, |
13 | | * software distributed under the License is distributed on an |
14 | | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | | * KIND, either express or implied. See the License for the |
16 | | * specific language governing permissions and limitations |
17 | | * under the License. |
18 | | */ |
19 | | |
20 | | #include <stdbool.h> |
21 | | |
22 | | #include "sopc_assert.h" |
23 | | #include "sopc_common_constants.h" |
24 | | #include "sopc_macros.h" |
25 | | #include "sopc_mem_alloc.h" |
26 | | #include "sopc_pubsub_constants.h" |
27 | | #include "sopc_pubsub_sks.h" |
28 | | #include "sopc_sk_secu_group_managers.h" |
29 | | |
30 | | void SOPC_PubSubSKS_Init(void) |
31 | 0 | { |
32 | | // Initialize the SK Managers for security groups |
33 | 0 | SOPC_SK_SecurityGroup_Managers_Init(); |
34 | 0 | } |
35 | | |
36 | | void SOPC_PubSubSKS_Clear(void) |
37 | 0 | { |
38 | | // Clear the SK Managers for security groups |
39 | 0 | SOPC_SK_SecurityGroup_Managers_Clear(); |
40 | 0 | } |
41 | | |
42 | | bool SOPC_PubSubSKS_AddSkManager(SOPC_SKManager* skm) |
43 | 0 | { |
44 | 0 | if (NULL == skm || NULL == skm->securityGroupId) |
45 | 0 | { |
46 | 0 | return false; |
47 | 0 | } |
48 | | |
49 | 0 | SOPC_SKManager* prevSkManager = SOPC_SK_SecurityGroup_GetSkManager(skm->securityGroupId); |
50 | 0 | bool result = SOPC_SK_SecurityGroup_SetSkManager(skm); |
51 | 0 | if (result && NULL != prevSkManager) |
52 | 0 | { |
53 | | // If a previous SK Manager exists, delete it |
54 | 0 | SOPC_SKManager_Clear(prevSkManager); |
55 | 0 | SOPC_Free(prevSkManager); |
56 | 0 | } |
57 | 0 | return result; |
58 | 0 | } |
59 | | |
60 | | SOPC_PubSubSKS_Keys* SOPC_PubSubSKS_GetSecurityKeys(const char* securityGroupid, uint32_t tokenId) |
61 | 0 | { |
62 | | // result |
63 | 0 | SOPC_PubSubSKS_Keys* returnedKeys = NULL; |
64 | | |
65 | | // Get keys from manager |
66 | 0 | SOPC_String* SecurityPolicyUri = NULL; |
67 | 0 | uint32_t FirstTokenId = 0; |
68 | 0 | SOPC_ByteString* Keys = NULL; |
69 | 0 | uint32_t NbKeys = 0; |
70 | 0 | uint64_t TimeToNextKey = 0; |
71 | 0 | uint64_t KeyLifetime = 0; |
72 | 0 | SOPC_SKManager* skm = SOPC_SK_SecurityGroup_GetSkManager(securityGroupid); |
73 | |
|
74 | 0 | if (NULL == skm) |
75 | 0 | { |
76 | 0 | return NULL; |
77 | 0 | } |
78 | | |
79 | 0 | SOPC_ReturnStatus status = |
80 | 0 | SOPC_SKManager_GetKeys(skm, tokenId, SOPC_PUBSUB_SKS_MAX_TOKEN_PER_CALL, &SecurityPolicyUri, &FirstTokenId, |
81 | 0 | &Keys, &NbKeys, &TimeToNextKey, &KeyLifetime); |
82 | | |
83 | | /** Fill Outputs **/ |
84 | | |
85 | | // Initialize returned keys if GetKeys returned valid Keys corresponding to requested token |
86 | 0 | SOPC_ByteString* byteString = NULL; |
87 | 0 | if (SOPC_STATUS_OK == status && 0 < NbKeys && |
88 | 0 | (SOPC_PUBSUB_SKS_CURRENT_TOKENID == tokenId || tokenId == FirstTokenId)) |
89 | 0 | { |
90 | 0 | byteString = &Keys[0]; |
91 | 0 | if ((32 + 32 + 4) == byteString->Length) |
92 | 0 | { |
93 | 0 | returnedKeys = SOPC_Calloc(1, sizeof(SOPC_PubSubSKS_Keys)); |
94 | 0 | } |
95 | 0 | } |
96 | |
|
97 | 0 | if (NULL != returnedKeys) |
98 | 0 | { |
99 | 0 | returnedKeys->tokenId = FirstTokenId; |
100 | 0 | returnedKeys->signingKey = SOPC_SecretBuffer_NewFromExposedBuffer(byteString->Data, 32); |
101 | 0 | returnedKeys->encryptKey = SOPC_SecretBuffer_NewFromExposedBuffer(&(byteString->Data[32]), 32); |
102 | 0 | returnedKeys->keyNonce = SOPC_SecretBuffer_NewFromExposedBuffer(&(byteString->Data[64]), 4); |
103 | 0 | if (NULL == returnedKeys->signingKey || NULL == returnedKeys->encryptKey || NULL == returnedKeys->keyNonce) |
104 | 0 | { |
105 | 0 | SOPC_PubSubSKS_Keys_Delete(returnedKeys); |
106 | 0 | SOPC_Free(returnedKeys); |
107 | 0 | returnedKeys = NULL; |
108 | 0 | } |
109 | 0 | } |
110 | |
|
111 | 0 | SOPC_String_Clear(SecurityPolicyUri); |
112 | 0 | SOPC_Free(SecurityPolicyUri); |
113 | 0 | for (uint32_t i = 0; i < NbKeys && NULL != Keys; i++) |
114 | 0 | { |
115 | 0 | SOPC_ByteString_Clear(&Keys[i]); |
116 | 0 | } |
117 | 0 | SOPC_Free(Keys); |
118 | |
|
119 | 0 | return returnedKeys; |
120 | 0 | } |
121 | | |
122 | | void SOPC_PubSubSKS_Keys_Delete(SOPC_PubSubSKS_Keys* keys) |
123 | 0 | { |
124 | 0 | if (NULL != keys) |
125 | 0 | { |
126 | 0 | SOPC_SecretBuffer_DeleteClear(keys->signingKey); |
127 | 0 | keys->signingKey = NULL; |
128 | 0 | SOPC_SecretBuffer_DeleteClear(keys->encryptKey); |
129 | 0 | keys->encryptKey = NULL; |
130 | 0 | SOPC_SecretBuffer_DeleteClear(keys->keyNonce); |
131 | 0 | keys->keyNonce = NULL; |
132 | 0 | } |
133 | 0 | } |
134 | | |
135 | | static bool mayAddSecurityGroupId(const char* securityGroupId) |
136 | 0 | { |
137 | 0 | SOPC_ASSERT(NULL != securityGroupId); |
138 | 0 | bool result = true; |
139 | 0 | if (NULL == SOPC_SK_SecurityGroup_GetSkManager(securityGroupId)) |
140 | 0 | { |
141 | 0 | SOPC_SKManager* skm = SOPC_SKManager_Create(securityGroupId, 0); |
142 | |
|
143 | 0 | if (NULL != skm) |
144 | 0 | { |
145 | 0 | result = SOPC_PubSubSKS_AddSkManager(skm); |
146 | 0 | } |
147 | 0 | else |
148 | 0 | { |
149 | 0 | SOPC_SKManager_Clear(skm); |
150 | 0 | SOPC_Free(skm); |
151 | 0 | result = false; |
152 | 0 | } |
153 | 0 | } |
154 | 0 | return result; |
155 | 0 | } |
156 | | |
157 | | bool SOPC_PubSubSKS_CreateManagersFromConfig(const SOPC_PubSubConfiguration* pubSubConfig) |
158 | 0 | { |
159 | 0 | if (NULL == pubSubConfig) |
160 | 0 | { |
161 | 0 | return false; |
162 | 0 | } |
163 | | |
164 | 0 | bool result = true; |
165 | | |
166 | | // Process publisher connections |
167 | 0 | for (uint32_t i = 0; i < SOPC_PubSubConfiguration_Nb_PubConnection(pubSubConfig); i++) |
168 | 0 | { |
169 | 0 | const SOPC_PubSubConnection* pubConnection = SOPC_PubSubConfiguration_Get_PubConnection_At(pubSubConfig, i); |
170 | | |
171 | | // Check writer groups |
172 | 0 | for (uint16_t j = 0; j < SOPC_PubSubConnection_Nb_WriterGroup(pubConnection); j++) |
173 | 0 | { |
174 | 0 | const SOPC_WriterGroup* group = SOPC_PubSubConnection_Get_WriterGroup_At(pubConnection, j); |
175 | 0 | const char* securityGroupId = SOPC_WriterGroup_Get_SecurityGroupId(group); |
176 | |
|
177 | 0 | if (NULL == securityGroupId && SOPC_SecurityMode_None != SOPC_WriterGroup_Get_SecurityMode(group)) |
178 | 0 | { |
179 | 0 | result = false; |
180 | 0 | } |
181 | 0 | else if (NULL != securityGroupId && result) |
182 | 0 | { |
183 | | // Ensure the security group id is added to the SKManager |
184 | 0 | result = mayAddSecurityGroupId(securityGroupId); |
185 | 0 | } |
186 | 0 | } |
187 | 0 | } |
188 | | |
189 | | // Process subscriber connections |
190 | 0 | for (uint32_t i = 0; i < SOPC_PubSubConfiguration_Nb_SubConnection(pubSubConfig); i++) |
191 | 0 | { |
192 | 0 | const SOPC_PubSubConnection* subConnection = SOPC_PubSubConfiguration_Get_SubConnection_At(pubSubConfig, i); |
193 | | |
194 | | // Check reader groups |
195 | 0 | for (uint16_t j = 0; j < SOPC_PubSubConnection_Nb_ReaderGroup(subConnection); j++) |
196 | 0 | { |
197 | 0 | const SOPC_ReaderGroup* group = SOPC_PubSubConnection_Get_ReaderGroup_At(subConnection, j); |
198 | 0 | const char* securityGroupId = SOPC_ReaderGroup_Get_SecurityGroupId(group); |
199 | |
|
200 | 0 | if (NULL == securityGroupId && SOPC_SecurityMode_None != SOPC_ReaderGroup_Get_SecurityMode(group)) |
201 | 0 | { |
202 | 0 | result = false; |
203 | 0 | } |
204 | 0 | else if (NULL != securityGroupId && result) |
205 | 0 | { |
206 | | // Ensure the security group id is added to the SKManager |
207 | 0 | result = mayAddSecurityGroupId(securityGroupId); |
208 | 0 | } |
209 | 0 | } |
210 | 0 | } |
211 | |
|
212 | 0 | return result; |
213 | 0 | } |
214 | | |
215 | | typedef struct |
216 | | { |
217 | | SOPC_SKscheduler* scheduler; |
218 | | SOPC_SKBuilder* builder; |
219 | | SOPC_SKProvider* provider; |
220 | | uint32_t msPeriod; |
221 | | bool result; |
222 | | } AddTaskContext; |
223 | | |
224 | | static void addTask(const char* securityGroupId, SOPC_SKManager* manager, void* userData) |
225 | 0 | { |
226 | 0 | SOPC_UNUSED_ARG(securityGroupId); |
227 | 0 | AddTaskContext* ctx = (AddTaskContext*) userData; |
228 | 0 | if (!ctx->result) |
229 | 0 | { |
230 | 0 | return; // Stop on first error |
231 | 0 | } |
232 | | |
233 | 0 | SOPC_ReturnStatus status = |
234 | 0 | SOPC_SKscheduler_AddTask(ctx->scheduler, ctx->builder, ctx->provider, manager, ctx->msPeriod); |
235 | 0 | ctx->result = (SOPC_STATUS_OK == status); |
236 | 0 | } |
237 | | |
238 | | bool SOPC_PubSubSKS_AddTasks(SOPC_SKscheduler* scheduler, |
239 | | SOPC_SKBuilder* builder, |
240 | | SOPC_SKProvider* provider, |
241 | | uint32_t msFirstUpdate) |
242 | 0 | { |
243 | 0 | if (NULL == scheduler || NULL == builder || NULL == provider) |
244 | 0 | { |
245 | 0 | return false; |
246 | 0 | } |
247 | | |
248 | 0 | AddTaskContext context = { |
249 | 0 | .scheduler = scheduler, .builder = builder, .provider = provider, .msPeriod = msFirstUpdate, .result = true}; |
250 | |
|
251 | 0 | SOPC_SecurityGroup_ForEach(addTask, &context); |
252 | |
|
253 | 0 | return context.result; |
254 | 0 | } |
255 | | |
256 | | SOPC_SKManager* SOPC_PubSubSKS_GetSkManager(const char* securityGroupId) |
257 | 0 | { |
258 | 0 | if (NULL == securityGroupId) |
259 | 0 | { |
260 | 0 | return NULL; |
261 | 0 | } |
262 | 0 | return SOPC_SK_SecurityGroup_GetSkManager(securityGroupId); |
263 | 0 | } |