Coverage Report

Created: 2025-10-10 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/S2OPC/src/Common/sks/sopc_sk_provider.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 <inttypes.h>
21
#include <stdio.h>
22
#include <string.h>
23
24
#include "sopc_assert.h"
25
#include "sopc_crypto_profiles.h"
26
#include "sopc_crypto_provider.h"
27
#include "sopc_logger.h"
28
#include "sopc_macros.h"
29
#include "sopc_mem_alloc.h"
30
#include "sopc_sk_provider.h"
31
32
/* Internal constantes */
33
0
#define SOPC_SK_PROVIDER_INTERNAL_PUBSUB_KEYS_SIZE (32 + 32 + 4)
34
0
#define SOPC_SK_PROVIDER_INTERNAL_PUBSUB_SECURITY_POLICY SOPC_SecurityPolicy_PubSub_Aes256_URI
35
36
typedef struct SOPC_SKProvider_RandomPubSub
37
{
38
    SOPC_CryptoProvider* cryptoProvider;
39
    uint32_t nbMaxKeys;
40
} SOPC_SKProvider_RandomPubSub;
41
42
static void SOPC_SKProvider_Clear_RandomPubSub_Aes256(void* data);
43
44
/*** DEFAULT IMPLEMENTATION FUNCTIONS ***/
45
46
typedef struct SOPC_SKProvider_TryList
47
{
48
    SOPC_SKProvider** providers;
49
    uint32_t nbProviders;
50
} SOPC_SKProvider_TryList;
51
52
/* TryList internal functions */
53
54
/**
55
 * \brief GetKeys function for SK Provider default implementation
56
 * Data is SOPC_SKProvider_TryList
57
 */
58
static SOPC_ReturnStatus SOPC_SKProvider_GetKeys_TryList(SOPC_SKProvider* skp,
59
                                                         const char* securityGroupId,
60
                                                         uint32_t StartingTokenId,
61
                                                         uint32_t NbRequestedToken,
62
                                                         SOPC_String** SecurityPolicyUri,
63
                                                         uint32_t* FirstTokenId,
64
                                                         SOPC_ByteString** Keys,
65
                                                         uint32_t* NbToken,
66
                                                         uint64_t* TimeToNextKey,
67
                                                         uint64_t* KeyLifetime)
68
0
{
69
0
    if (NULL == skp || 0 == skp->data || NULL == Keys || NULL == NbToken || 0 == NbRequestedToken)
70
0
    {
71
0
        return SOPC_STATUS_INVALID_PARAMETERS;
72
0
    }
73
74
0
    SOPC_ReturnStatus status = SOPC_STATUS_NOK;
75
0
    SOPC_SKProvider_TryList* data = (SOPC_SKProvider_TryList*) skp->data;
76
0
    SOPC_ASSERT(NULL != data);
77
0
    SOPC_ASSERT(NULL != data->providers);
78
0
    for (uint32_t i = 0; i < data->nbProviders; i++)
79
0
    {
80
0
        SOPC_Logger_TraceInfo(SOPC_LOG_MODULE_COMMON, "Try GetKeys with provider %" PRIu32, i + 1);
81
0
        status = SOPC_SKProvider_GetKeys(data->providers[i], securityGroupId, StartingTokenId, NbRequestedToken,
82
0
                                         SecurityPolicyUri, FirstTokenId, Keys, NbToken, TimeToNextKey, KeyLifetime);
83
0
        if (SOPC_STATUS_OK == status && 0 < *NbToken)
84
0
        {
85
0
            break;
86
0
        }
87
0
    }
88
89
0
    return status;
90
0
}
91
92
static void SOPC_SKProvider_Clear_TryList(void* pdata)
93
0
{
94
0
    if (NULL == pdata)
95
0
    {
96
0
        return;
97
0
    }
98
99
0
    SOPC_SKProvider_TryList* data = (SOPC_SKProvider_TryList*) pdata;
100
0
    SOPC_ASSERT(NULL != data->providers);
101
0
    for (uint32_t i = 0; i < data->nbProviders; i++)
102
0
    {
103
0
        SOPC_SKProvider_Clear(data->providers[i]);
104
0
        SOPC_Free(data->providers[i]);
105
0
    }
106
0
    SOPC_Free(data->providers);
107
0
    data->providers = NULL;
108
0
    SOPC_Free(data);
109
0
}
110
111
/* RandomPubSub internal functions */
112
113
/**
114
 * \brief GetKeys function for SK Provider default implementation
115
 * Data is SOPC_CryptoProvider
116
 */
117
static SOPC_ReturnStatus SOPC_SKProvider_GetKeys_RandomPubSub_Aes256(SOPC_SKProvider* skp,
118
                                                                     const char* securityGroupId,
119
                                                                     uint32_t StartingTokenId,
120
                                                                     uint32_t NbRequestedToken,
121
                                                                     SOPC_String** SecurityPolicyUri,
122
                                                                     uint32_t* FirstTokenId,
123
                                                                     SOPC_ByteString** Keys,
124
                                                                     uint32_t* NbToken,
125
                                                                     uint64_t* TimeToNextKey,
126
                                                                     uint64_t* KeyLifetime)
127
0
{
128
    /* Not used*/
129
0
    SOPC_UNUSED_ARG(securityGroupId); // not necessary as we generate fresh keys anyway
130
0
    SOPC_UNUSED_ARG(StartingTokenId);
131
0
    SOPC_UNUSED_ARG(SecurityPolicyUri);
132
0
    SOPC_UNUSED_ARG(FirstTokenId);
133
0
    SOPC_UNUSED_ARG(TimeToNextKey);
134
0
    SOPC_UNUSED_ARG(KeyLifetime);
135
136
    /* Only skp */
137
0
    if (NULL == skp || 0 == skp->data || NULL == Keys || NULL == NbToken || 0 == NbRequestedToken)
138
0
    {
139
0
        return SOPC_STATUS_INVALID_PARAMETERS;
140
0
    }
141
142
0
    SOPC_ReturnStatus status = SOPC_STATUS_OK;
143
144
0
    SOPC_SKProvider_RandomPubSub* data = (SOPC_SKProvider_RandomPubSub*) skp->data;
145
146
0
    if (0 == data->nbMaxKeys)
147
0
    {
148
0
        return SOPC_STATUS_INVALID_PARAMETERS;
149
0
    }
150
151
0
    uint32_t nbKeys = (NbRequestedToken < data->nbMaxKeys) ? NbRequestedToken : data->nbMaxKeys;
152
153
0
    SOPC_ByteString* generatedKeys = SOPC_Calloc(nbKeys, sizeof(SOPC_ByteString));
154
0
    if (NULL == generatedKeys)
155
0
    {
156
0
        return SOPC_STATUS_OUT_OF_MEMORY;
157
0
    }
158
159
    /* Generate Random Keys and copy in out parameter */
160
0
    uint32_t keyIndex = 0;
161
0
    for (keyIndex = 0; keyIndex < nbKeys && SOPC_STATUS_OK == status; keyIndex++)
162
0
    {
163
0
        SOPC_ExposedBuffer* ppBuffer = NULL;
164
0
        SOPC_ByteString_Initialize(&generatedKeys[keyIndex]);
165
0
        status = SOPC_CryptoProvider_GenerateRandomBytes(data->cryptoProvider,
166
0
                                                         SOPC_SK_PROVIDER_INTERNAL_PUBSUB_KEYS_SIZE, &ppBuffer);
167
0
        if (SOPC_STATUS_OK == status)
168
0
        {
169
0
            status = SOPC_ByteString_CopyFromBytes((&generatedKeys[keyIndex]), ppBuffer,
170
0
                                                   SOPC_SK_PROVIDER_INTERNAL_PUBSUB_KEYS_SIZE);
171
0
        }
172
0
        SOPC_Free(ppBuffer);
173
0
    }
174
175
0
    if (SOPC_STATUS_OK != status)
176
0
    {
177
0
        *NbToken = 0;
178
        /* Clear only initialized Keys */
179
0
        for (uint32_t i = 0; i < keyIndex; i++)
180
0
        {
181
0
            SOPC_ByteString_Clear(&generatedKeys[i]);
182
0
        }
183
0
        SOPC_Free(generatedKeys);
184
0
    }
185
0
    else
186
0
    {
187
0
        *Keys = generatedKeys;
188
0
        *NbToken = nbKeys;
189
0
    }
190
0
    return status;
191
0
}
192
193
static void SOPC_SKProvider_Clear_RandomPubSub_Aes256(void* pdata)
194
0
{
195
0
    if (NULL == pdata)
196
0
    {
197
0
        return;
198
0
    }
199
200
0
    SOPC_SKProvider_RandomPubSub* data = (SOPC_SKProvider_RandomPubSub*) pdata;
201
0
    SOPC_CryptoProvider_Free(data->cryptoProvider);
202
0
    data->cryptoProvider = NULL;
203
0
    data->nbMaxKeys = 0;
204
0
    SOPC_Free(data);
205
0
}
206
207
/*** API FUNCTIONS ***/
208
209
SOPC_SKProvider* SOPC_SKProvider_TryList_Create(SOPC_SKProvider** providers, uint32_t nbProviders)
210
0
{
211
0
    if (NULL == providers || 0 == nbProviders)
212
0
    {
213
0
        return NULL;
214
0
    }
215
216
0
    SOPC_SKProvider* skp = SOPC_Malloc(sizeof(SOPC_SKProvider));
217
0
    if (NULL == skp)
218
0
    {
219
0
        return NULL;
220
0
    }
221
222
0
    SOPC_SKProvider_TryList* data = SOPC_Calloc(1, sizeof(SOPC_SKProvider_TryList));
223
0
    if (NULL == data)
224
0
    {
225
0
        SOPC_Free(skp);
226
0
        return NULL;
227
0
    }
228
229
0
    skp->data = (uintptr_t) data;
230
0
    data->providers = providers;
231
0
    data->nbProviders = nbProviders;
232
233
0
    skp->ptrGetKeys = SOPC_SKProvider_GetKeys_TryList;
234
0
    skp->ptrClear = SOPC_SKProvider_Clear_TryList;
235
0
    skp->referencesCounter = 0;
236
237
0
    return skp;
238
0
}
239
240
SOPC_SKProvider* SOPC_SKProvider_RandomPubSub_Create(uint32_t maxKeys)
241
0
{
242
0
    SOPC_SKProvider* skp = SOPC_Malloc(sizeof(SOPC_SKProvider));
243
0
    if (NULL == skp)
244
0
    {
245
0
        return NULL;
246
0
    }
247
248
0
    skp->data = (uintptr_t) SOPC_Calloc(1, sizeof(SOPC_SKProvider_RandomPubSub));
249
0
    if ((uintptr_t) NULL == skp->data)
250
0
    {
251
0
        SOPC_Free(skp);
252
0
        return NULL;
253
0
    }
254
255
0
    SOPC_SKProvider_RandomPubSub* data = (SOPC_SKProvider_RandomPubSub*) skp->data;
256
0
    data->cryptoProvider = SOPC_CryptoProvider_CreatePubSub(SOPC_SK_PROVIDER_INTERNAL_PUBSUB_SECURITY_POLICY);
257
0
    if (NULL == data->cryptoProvider)
258
0
    {
259
0
        SOPC_Free((void*) skp->data);
260
0
        SOPC_Free(skp);
261
0
        return NULL;
262
0
    }
263
0
    data->nbMaxKeys = maxKeys;
264
265
0
    skp->ptrGetKeys = SOPC_SKProvider_GetKeys_RandomPubSub_Aes256;
266
0
    skp->ptrClear = SOPC_SKProvider_Clear_RandomPubSub_Aes256;
267
0
    skp->referencesCounter = 0;
268
269
0
    return skp;
270
0
}
271
272
SOPC_ReturnStatus SOPC_SKProvider_GetKeys(SOPC_SKProvider* skp,
273
                                          const char* securityGroupId,
274
                                          uint32_t StartingTokenId,
275
                                          uint32_t NbRequestedToken,
276
                                          SOPC_String** SecurityPolicyUri,
277
                                          uint32_t* FirstTokenId,
278
                                          SOPC_ByteString** Keys,
279
                                          uint32_t* NbKeys,
280
                                          uint64_t* TimeToNextKey,
281
                                          uint64_t* KeyLifetime)
282
0
{
283
0
    if (NULL == skp)
284
0
    {
285
0
        return SOPC_STATUS_INVALID_PARAMETERS;
286
0
    }
287
0
    return skp->ptrGetKeys(skp, securityGroupId, StartingTokenId, NbRequestedToken, SecurityPolicyUri, FirstTokenId,
288
0
                           Keys, NbKeys, TimeToNextKey, KeyLifetime);
289
0
}
290
291
void SOPC_SKProvider_Clear(SOPC_SKProvider* skp)
292
0
{
293
0
    if (NULL != skp)
294
0
    {
295
0
        if (NULL != skp->ptrClear)
296
0
        {
297
0
            skp->ptrClear((void*) skp->data);
298
0
        }
299
0
        skp->data = (uintptr_t) NULL;
300
0
    }
301
0
}
302
303
void SOPC_SKProvider_MayDelete(SOPC_SKProvider** skp)
304
0
{
305
0
    if (NULL == skp || NULL == *skp)
306
0
    {
307
0
        return;
308
0
    }
309
0
    SOPC_SKProvider* provider = *skp;
310
    // Updates the counter if not already zero
311
0
    provider->referencesCounter = provider->referencesCounter > 0 ? provider->referencesCounter - 1 : 0;
312
0
    if (provider->referencesCounter == 0)
313
0
    {
314
0
        SOPC_SKProvider_Clear(provider);
315
0
        SOPC_Free(provider);
316
        *skp = NULL;
317
0
    }
318
0
}