Coverage Report

Created: 2025-07-18 06:54

/src/S2OPC/src/Common/sks/sopc_sk_builder.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 <stdio.h>
21
#include <string.h>
22
23
#include "sopc_assert.h"
24
#include "sopc_crypto_profiles.h"
25
#include "sopc_crypto_provider.h"
26
#include "sopc_logger.h"
27
#include "sopc_mem_alloc.h"
28
#include "sopc_sk_builder.h"
29
30
/*** DEFAULT IMPLEMENTATION FUNCTIONS ***/
31
32
static SOPC_ReturnStatus SOPC_SKBuilder_Update_Default_Setter(SOPC_SKBuilder* skb,
33
                                                              SOPC_SKProvider* skp,
34
                                                              SOPC_SKManager* skm)
35
0
{
36
0
    SOPC_ASSERT(NULL != skb && NULL != skp && NULL != skm);
37
38
0
    SOPC_String* SecurityPolicyUri = NULL;
39
0
    uint32_t FirstTokenId = 0;
40
0
    SOPC_ByteString* Keys = NULL;
41
0
    uint32_t NbToken = 0;
42
0
    uint32_t TimeToNextKey = 0;
43
0
    uint32_t KeyLifetime = 0;
44
45
0
    SOPC_ReturnStatus status =
46
0
        SOPC_SKProvider_GetKeys(skp, skm->securityGroupId, SOPC_SK_MANAGER_CURRENT_TOKEN_ID, UINT32_MAX,
47
0
                                &SecurityPolicyUri, &FirstTokenId, &Keys, &NbToken, &TimeToNextKey, &KeyLifetime);
48
49
0
    if (SOPC_STATUS_OK == status && NULL != Keys && 0 < NbToken)
50
0
    {
51
0
        status =
52
0
            SOPC_SKManager_SetKeys(skm, SecurityPolicyUri, FirstTokenId, Keys, NbToken, TimeToNextKey, KeyLifetime);
53
54
0
        if (SOPC_STATUS_OK != status)
55
0
        {
56
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, "Security Key Service: Error Builder cannot set Keys");
57
0
        }
58
59
0
        for (uint32_t i = 0; i < NbToken; i++)
60
0
        {
61
0
            SOPC_ByteString_Clear(&Keys[i]);
62
0
        }
63
0
        SOPC_Free(Keys);
64
0
        SOPC_String_Clear(SecurityPolicyUri);
65
0
        SOPC_Free(SecurityPolicyUri);
66
0
    }
67
0
    else
68
0
    {
69
0
        SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON,
70
0
                               "Security Key Service: Error in Builder By SKS - cannot load keys");
71
0
    }
72
0
    return status;
73
0
}
74
75
typedef struct SOPC_SKBuilder_TruncateData
76
{
77
    SOPC_SKBuilder* skb;
78
    uint32_t sizeMax;
79
} SOPC_SKBuilder_TruncateData;
80
81
static SOPC_ReturnStatus SOPC_SKBuilder_Update_Truncate(SOPC_SKBuilder* skb, SOPC_SKProvider* skp, SOPC_SKManager* skm)
82
0
{
83
0
    SOPC_ASSERT(NULL != skb && NULL != skb->data);
84
85
0
    SOPC_SKBuilder_TruncateData* data = (SOPC_SKBuilder_TruncateData*) skb->data;
86
87
0
    SOPC_ReturnStatus status = SOPC_SKBuilder_Update(data->skb, skp, skm);
88
0
    if (SOPC_STATUS_OK != status)
89
0
    {
90
0
        return status;
91
0
    }
92
93
0
    uint32_t size = SOPC_SKManager_Size(skm);
94
95
0
    if (size > data->sizeMax)
96
0
    {
97
0
        SOPC_String* SecurityPolicyUri = NULL;
98
0
        uint32_t FirstTokenId = 0;
99
0
        SOPC_ByteString* Keys = NULL;
100
0
        uint32_t NbToken = 0;
101
0
        uint32_t TimeToNextKey = 0;
102
0
        uint32_t KeyLifetime = 0;
103
104
0
        status = SOPC_SKManager_GetKeys(skm, SOPC_SK_MANAGER_CURRENT_TOKEN_ID, data->sizeMax, &SecurityPolicyUri,
105
0
                                        &FirstTokenId, &Keys, &NbToken, &TimeToNextKey, &KeyLifetime);
106
0
        if (SOPC_STATUS_OK == status)
107
0
        {
108
0
            status =
109
0
                SOPC_SKManager_SetKeys(skm, SecurityPolicyUri, FirstTokenId, Keys, NbToken, TimeToNextKey, KeyLifetime);
110
0
        }
111
112
0
        SOPC_String_Clear(SecurityPolicyUri);
113
0
        SOPC_Free(SecurityPolicyUri);
114
0
        for (uint32_t i = 0; i < NbToken; i++)
115
0
        {
116
0
            SOPC_ByteString_Clear(&Keys[i]);
117
0
        }
118
0
        SOPC_Free(Keys);
119
0
    }
120
0
    return status;
121
0
}
122
123
static void SOPC_SKBuilder_Clear_Truncate(void* data)
124
0
{
125
0
    SOPC_SKBuilder_TruncateData* truncateData = (SOPC_SKBuilder_TruncateData*) data;
126
0
    SOPC_SKBuilder_Clear(truncateData->skb);
127
0
    SOPC_Free(truncateData->skb);
128
0
}
129
130
static SOPC_ReturnStatus SOPC_SKBuilder_Update_Default_Append(SOPC_SKBuilder* skb,
131
                                                              SOPC_SKProvider* skp,
132
                                                              SOPC_SKManager* skm)
133
0
{
134
0
    SOPC_ASSERT(NULL != skb && NULL != skp && NULL != skm);
135
136
0
    SOPC_ByteString* Keys = NULL;
137
0
    uint32_t NbKeys = 0;
138
139
    // TODO add a security group list in data and current token
140
0
    SOPC_ReturnStatus status =
141
0
        SOPC_SKProvider_GetKeys(skp, skm->securityGroupId, 0, UINT32_MAX, NULL, NULL, &Keys, &NbKeys, NULL, NULL);
142
143
0
    if (SOPC_STATUS_OK == status && NULL != Keys && 0 < NbKeys)
144
0
    {
145
0
        uint32_t addedKeys = SOPC_SKManager_AddKeys(skm, Keys, NbKeys);
146
147
0
        if (addedKeys != NbKeys)
148
0
        {
149
0
            status = SOPC_STATUS_NOK;
150
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, "Security Key Builder: Error with SK Manager");
151
0
        }
152
0
        for (uint32_t i = 0; i < NbKeys; i++)
153
0
        {
154
0
            SOPC_ByteString_Clear(&Keys[i]);
155
0
        }
156
0
        SOPC_Free(Keys);
157
0
    }
158
0
    else
159
0
    {
160
0
        SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON,
161
0
                               "Security Key Builder: Error with SK Provider - cannot load keys");
162
0
    }
163
164
0
    return status;
165
0
}
166
167
typedef struct SOPC_SKBuilder_CallbackData
168
{
169
    SOPC_SKBuilder* skb;
170
    SOPC_SKBuilder_Callback_Func callback;
171
    uintptr_t userParam;
172
} SOPC_SKBuilder_CallbackData;
173
174
static SOPC_ReturnStatus SOPC_SKBuilder_Update_Callback(SOPC_SKBuilder* skb, SOPC_SKProvider* skp, SOPC_SKManager* skm)
175
0
{
176
0
    SOPC_ASSERT(NULL != skb && NULL != skb->data);
177
178
0
    SOPC_SKBuilder_CallbackData* data = (SOPC_SKBuilder_CallbackData*) skb->data;
179
180
0
    SOPC_ReturnStatus status = SOPC_SKBuilder_Update(data->skb, skp, skm);
181
0
    if (SOPC_STATUS_OK == status && NULL != data->callback)
182
0
    {
183
0
        data->callback(skb, skm, data->userParam);
184
0
    }
185
186
0
    return status;
187
0
}
188
189
static void SOPC_SKBuilder_Clear_Callback(void* data)
190
0
{
191
0
    SOPC_SKBuilder_CallbackData* callbackData = (SOPC_SKBuilder_CallbackData*) data;
192
0
    SOPC_SKBuilder_Clear(callbackData->skb);
193
0
    SOPC_Free(callbackData->skb);
194
0
}
195
196
/*** API FUNCTIONS ***/
197
198
SOPC_SKBuilder* SOPC_SKBuilder_Append_Create(void)
199
0
{
200
0
    SOPC_SKBuilder* skb = SOPC_Calloc(1, sizeof(SOPC_SKBuilder));
201
0
    if (NULL == skb)
202
0
    {
203
0
        return NULL;
204
0
    }
205
206
0
    skb->data = NULL;
207
0
    skb->referencesCounter = 0;
208
209
0
    skb->ptrUpdate = SOPC_SKBuilder_Update_Default_Append;
210
0
    skb->ptrClear = NULL;
211
212
0
    return skb;
213
0
}
214
215
SOPC_SKBuilder* SOPC_SKBuilder_Truncate_Create(SOPC_SKBuilder* skb, uint32_t sizeMax)
216
0
{
217
0
    SOPC_SKBuilder* result = SOPC_Calloc(1, sizeof(SOPC_SKBuilder));
218
0
    if (NULL == result)
219
0
    {
220
0
        return NULL;
221
0
    }
222
223
0
    result->data = SOPC_Calloc(1, sizeof(SOPC_SKBuilder_TruncateData));
224
0
    if (NULL == result->data)
225
0
    {
226
0
        SOPC_Free(result);
227
0
        return NULL;
228
0
    }
229
230
0
    SOPC_SKBuilder_TruncateData* data = (SOPC_SKBuilder_TruncateData*) result->data;
231
232
0
    data->skb = skb;
233
0
    data->sizeMax = sizeMax;
234
235
0
    result->ptrUpdate = SOPC_SKBuilder_Update_Truncate;
236
0
    result->ptrClear = SOPC_SKBuilder_Clear_Truncate;
237
238
0
    return result;
239
0
}
240
241
SOPC_SKBuilder* SOPC_SKBuilder_Setter_Create(void)
242
0
{
243
0
    SOPC_SKBuilder* skb = SOPC_Calloc(1, sizeof(SOPC_SKBuilder));
244
0
    if (NULL == skb)
245
0
    {
246
0
        return NULL;
247
0
    }
248
249
0
    skb->data = NULL;
250
0
    skb->referencesCounter = 0;
251
252
0
    skb->ptrUpdate = SOPC_SKBuilder_Update_Default_Setter;
253
0
    skb->ptrClear = NULL;
254
255
0
    return skb;
256
0
}
257
258
SOPC_SKBuilder* SOPC_SKBuilder_Callback_Create(SOPC_SKBuilder* skb,
259
                                               SOPC_SKBuilder_Callback_Func callback,
260
                                               uintptr_t userParam)
261
0
{
262
0
    SOPC_SKBuilder* result = SOPC_Calloc(1, sizeof(SOPC_SKBuilder));
263
0
    if (NULL == result)
264
0
    {
265
0
        return NULL;
266
0
    }
267
268
0
    result->data = SOPC_Calloc(1, sizeof(SOPC_SKBuilder_CallbackData));
269
0
    if (NULL == result->data)
270
0
    {
271
0
        SOPC_Free(result);
272
0
        return NULL;
273
0
    }
274
275
0
    SOPC_SKBuilder_CallbackData* data = (SOPC_SKBuilder_CallbackData*) result->data;
276
277
0
    data->skb = skb;
278
0
    data->callback = callback;
279
0
    data->userParam = userParam;
280
281
0
    result->ptrUpdate = SOPC_SKBuilder_Update_Callback;
282
0
    result->ptrClear = SOPC_SKBuilder_Clear_Callback;
283
284
0
    return result;
285
0
}
286
287
SOPC_ReturnStatus SOPC_SKBuilder_Update(SOPC_SKBuilder* skb, SOPC_SKProvider* skp, SOPC_SKManager* skm)
288
0
{
289
0
    if (NULL == skb || NULL == skb->ptrUpdate)
290
0
    {
291
0
        return SOPC_STATUS_INVALID_PARAMETERS;
292
0
    }
293
0
    return skb->ptrUpdate(skb, skp, skm);
294
0
}
295
296
void SOPC_SKBuilder_Clear(SOPC_SKBuilder* skb)
297
0
{
298
0
    if (NULL != skb)
299
0
    {
300
0
        if (NULL != skb->ptrClear)
301
0
        {
302
0
            skb->ptrClear(skb->data);
303
0
        }
304
0
        SOPC_Free(skb->data);
305
0
        skb->data = NULL;
306
0
        skb->referencesCounter = 0;
307
0
    }
308
0
}
309
310
void SOPC_SKBuilder_MayDelete(SOPC_SKBuilder** skb)
311
0
{
312
0
    if (NULL == skb || NULL == *skb)
313
0
    {
314
0
        return;
315
0
    }
316
0
    SOPC_SKBuilder* builder = *skb;
317
    // Updates the counter if not already zero
318
0
    builder->referencesCounter = builder->referencesCounter > 0 ? builder->referencesCounter - 1 : 0;
319
0
    if (builder->referencesCounter == 0)
320
0
    {
321
0
        SOPC_SKBuilder_Clear(builder);
322
0
        SOPC_Free(builder);
323
0
        *skb = NULL;
324
0
    }
325
0
}