Coverage Report

Created: 2025-08-26 06:59

/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
}