Coverage Report

Created: 2026-03-07 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/S2OPC/src/PubSub/security/sopc_pubsub_sks.c
Line
Count
Source
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; result && 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; result && 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
0
            const SOPC_SecurityMode_Type secuMode = SOPC_WriterGroup_Get_SecurityMode(group);
177
178
0
            if (NULL == securityGroupId && SOPC_SecurityMode_None != secuMode)
179
0
            {
180
0
                result = false;
181
0
            }
182
0
            else if (SOPC_SecurityMode_None != secuMode)
183
0
            {
184
                // Ensure the security group id is added to the SKManager
185
0
                result = mayAddSecurityGroupId(securityGroupId);
186
0
            }
187
0
        }
188
0
    }
189
190
    // Process subscriber connections
191
0
    for (uint32_t i = 0; result && i < SOPC_PubSubConfiguration_Nb_SubConnection(pubSubConfig); i++)
192
0
    {
193
0
        const SOPC_PubSubConnection* subConnection = SOPC_PubSubConfiguration_Get_SubConnection_At(pubSubConfig, i);
194
195
        // Check reader groups
196
0
        for (uint16_t j = 0; result && j < SOPC_PubSubConnection_Nb_ReaderGroup(subConnection); j++)
197
0
        {
198
0
            const SOPC_ReaderGroup* group = SOPC_PubSubConnection_Get_ReaderGroup_At(subConnection, j);
199
0
            const char* securityGroupId = SOPC_ReaderGroup_Get_SecurityGroupId(group);
200
0
            const SOPC_SecurityMode_Type secuMode = SOPC_ReaderGroup_Get_SecurityMode(group);
201
202
0
            if (NULL == securityGroupId && SOPC_SecurityMode_None != secuMode)
203
0
            {
204
0
                result = false;
205
0
            }
206
0
            else if (SOPC_SecurityMode_None != secuMode)
207
0
            {
208
                // Ensure the security group id is added to the SKManager
209
0
                result = mayAddSecurityGroupId(securityGroupId);
210
0
            }
211
0
        }
212
0
    }
213
214
0
    return result;
215
0
}
216
217
typedef struct
218
{
219
    SOPC_SKscheduler* scheduler;
220
    SOPC_SKBuilder* builder;
221
    SOPC_SKProvider* provider;
222
    uint32_t msPeriod;
223
    bool result;
224
} AddTaskContext;
225
226
static void addTask(const char* securityGroupId, SOPC_SKManager* manager, void* userData)
227
0
{
228
0
    SOPC_UNUSED_ARG(securityGroupId);
229
0
    AddTaskContext* ctx = (AddTaskContext*) userData;
230
0
    if (!ctx->result)
231
0
    {
232
0
        return; // Stop on first error
233
0
    }
234
235
0
    SOPC_ReturnStatus status =
236
0
        SOPC_SKscheduler_AddTask(ctx->scheduler, ctx->builder, ctx->provider, manager, ctx->msPeriod);
237
0
    ctx->result = (SOPC_STATUS_OK == status);
238
0
}
239
240
bool SOPC_PubSubSKS_AddTasks(SOPC_SKscheduler* scheduler,
241
                             SOPC_SKBuilder* builder,
242
                             SOPC_SKProvider* provider,
243
                             uint32_t msFirstUpdate)
244
0
{
245
0
    if (NULL == scheduler || NULL == builder || NULL == provider)
246
0
    {
247
0
        return false;
248
0
    }
249
250
0
    AddTaskContext context = {
251
0
        .scheduler = scheduler, .builder = builder, .provider = provider, .msPeriod = msFirstUpdate, .result = true};
252
253
0
    SOPC_SecurityGroup_ForEach(addTask, &context);
254
255
0
    return context.result;
256
0
}
257
258
SOPC_SKManager* SOPC_PubSubSKS_GetSkManager(const char* securityGroupId)
259
0
{
260
0
    if (NULL == securityGroupId)
261
0
    {
262
0
        return NULL;
263
0
    }
264
0
    return SOPC_SK_SecurityGroup_GetSkManager(securityGroupId);
265
0
}