/src/S2OPC/src/Common/crypto/sopc_pki_stack.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 <stddef.h> |
21 | | #include <string.h> |
22 | | |
23 | | #include "sopc_assert.h" |
24 | | #include "sopc_buffer.h" |
25 | | #include "sopc_common_constants.h" |
26 | | #include "sopc_crypto_profiles.h" |
27 | | #include "sopc_filesystem.h" |
28 | | #include "sopc_helper_string.h" |
29 | | #include "sopc_key_manager_lib_itf.h" |
30 | | #include "sopc_logger.h" |
31 | | #include "sopc_macros.h" |
32 | | #include "sopc_mem_alloc.h" |
33 | | #include "sopc_pki_stack.h" |
34 | | #include "sopc_pki_stack_lib_internal_itf.h" |
35 | | #include "sopc_pki_struct_lib_internal.h" |
36 | | |
37 | | #ifndef STR_TRUSTLIST_NAME |
38 | 0 | #define STR_TRUSTLIST_NAME "/updatedTrustList" |
39 | | #endif |
40 | | |
41 | 0 | #define STR_TRUSTED "/trusted" |
42 | 0 | #define STR_TRUSTED_CERTS "/trusted/certs" |
43 | 0 | #define STR_TRUSTED_CRL "/trusted/crl" |
44 | 0 | #define STR_ISSUERS "/issuers" |
45 | 0 | #define STR_ISSUERS_CERTS "/issuers/certs" |
46 | 0 | #define STR_ISSUERS_CRL "/issuers/crl" |
47 | 0 | #define STR_REJECTED "/rejected" |
48 | | |
49 | 0 | #define HEX_THUMBPRINT_SIZE 40 |
50 | | |
51 | | #ifndef WITH_NO_CRYPTO |
52 | | |
53 | | static const SOPC_PKI_LeafProfile g_leaf_profile_rsa_sha256_2048_4096 = {.mdSign = SOPC_PKI_MD_SHA256, |
54 | | .pkAlgo = SOPC_PKI_PK_RSA, |
55 | | .RSAMinimumKeySize = 2048, |
56 | | .RSAMaximumKeySize = 4096, |
57 | | .bApplySecurityPolicy = true, |
58 | | .keyUsage = SOPC_PKI_KU_NONE, |
59 | | .extendedKeyUsage = SOPC_PKI_EKU_NONE, |
60 | | .sanApplicationUri = NULL, |
61 | | .sanURL = NULL}; |
62 | | |
63 | | static const SOPC_PKI_ChainProfile g_chain_profile_rsa_sha256_2048 = {.curves = SOPC_PKI_CURVES_ANY, |
64 | | .mdSign = SOPC_PKI_MD_SHA256_OR_ABOVE, |
65 | | .pkAlgo = SOPC_PKI_PK_RSA, |
66 | | .RSAMinimumKeySize = 2048, |
67 | | .bDisableRevocationCheck = false}; |
68 | | |
69 | | static const SOPC_PKI_LeafProfile g_leaf_profile_rsa_sha1_1024_2048 = {.mdSign = SOPC_PKI_MD_SHA1_AND_SHA256, |
70 | | .pkAlgo = SOPC_PKI_PK_RSA, |
71 | | .RSAMinimumKeySize = 1024, |
72 | | .RSAMaximumKeySize = 2048, |
73 | | .bApplySecurityPolicy = true, |
74 | | .keyUsage = SOPC_PKI_KU_NONE, |
75 | | .extendedKeyUsage = SOPC_PKI_EKU_NONE, |
76 | | .sanApplicationUri = NULL, |
77 | | .sanURL = NULL}; |
78 | | |
79 | | static const SOPC_PKI_ChainProfile g_chain_profile_rsa_sha1_1024 = {.curves = SOPC_PKI_CURVES_ANY, |
80 | | .mdSign = SOPC_PKI_MD_SHA1_OR_ABOVE, |
81 | | .pkAlgo = SOPC_PKI_PK_RSA, |
82 | | .RSAMinimumKeySize = 1024, |
83 | | .bDisableRevocationCheck = false}; |
84 | | |
85 | | typedef struct Profile_Cfg |
86 | | { |
87 | | const SOPC_PKI_ChainProfile* chain; |
88 | | const SOPC_PKI_LeafProfile* leaf; |
89 | | const SOPC_SecurityPolicy_ID id; |
90 | | } Profile_Cfg; |
91 | | |
92 | | static const Profile_Cfg g_all_profiles[] = { |
93 | | {.id = SOPC_SecurityPolicy_Aes256Sha256RsaPss_ID, |
94 | | .leaf = &g_leaf_profile_rsa_sha256_2048_4096, |
95 | | .chain = &g_chain_profile_rsa_sha256_2048}, |
96 | | {.id = SOPC_SecurityPolicy_Aes128Sha256RsaOaep_ID, |
97 | | .leaf = &g_leaf_profile_rsa_sha256_2048_4096, |
98 | | .chain = &g_chain_profile_rsa_sha256_2048}, |
99 | | {.id = SOPC_SecurityPolicy_Basic256Sha256_ID, |
100 | | .leaf = &g_leaf_profile_rsa_sha256_2048_4096, |
101 | | .chain = &g_chain_profile_rsa_sha256_2048}, |
102 | | {.id = SOPC_SecurityPolicy_Basic256_ID, |
103 | | .leaf = &g_leaf_profile_rsa_sha1_1024_2048, |
104 | | .chain = &g_chain_profile_rsa_sha1_1024}, |
105 | | }; |
106 | | |
107 | | static const SOPC_PKI_KeyUsage_Mask g_appKU = SOPC_PKI_KU_KEY_ENCIPHERMENT | SOPC_PKI_KU_KEY_DATA_ENCIPHERMENT | |
108 | | SOPC_PKI_KU_DIGITAL_SIGNATURE | SOPC_PKI_KU_NON_REPUDIATION; |
109 | | static const SOPC_PKI_KeyUsage_Mask g_usrKU = |
110 | | SOPC_PKI_KU_DIGITAL_SIGNATURE; // it is not part of the OPC UA but it makes sense to keep it |
111 | | static const SOPC_PKI_ExtendedKeyUsage_Mask g_clientEKU = SOPC_PKI_EKU_SERVER_AUTH; |
112 | | static const SOPC_PKI_ExtendedKeyUsage_Mask g_serverEKU = SOPC_PKI_EKU_CLIENT_AUTH; |
113 | | static const SOPC_PKI_ExtendedKeyUsage_Mask g_userEKU = SOPC_PKI_EKU_NONE; |
114 | | |
115 | | /** |
116 | | * Static functions declaration |
117 | | */ |
118 | | |
119 | | static void sopc_pki_clear(SOPC_PKIProvider* pPKI); |
120 | | |
121 | | // Copy newPKI content into currentPKI by preserving currentPKI mutex and then clear previous PKI content. |
122 | | // Then frees the new PKI structure. |
123 | | static void sopc_internal_replace_pki_and_clear(SOPC_PKIProvider* currentPKI, SOPC_PKIProvider** newPKI); |
124 | | |
125 | | static SOPC_ReturnStatus sopc_pki_check_application_uri(const SOPC_CertificateList* pToValidate, |
126 | | const char* applicationUri); |
127 | | |
128 | | static SOPC_ReturnStatus sopc_pki_check_security_level_of_the_update(const SOPC_CertificateList* pTrustedCerts, |
129 | | const SOPC_CRLList* pTrustedCrl, |
130 | | const SOPC_CertificateList* pIssuerCerts, |
131 | | const SOPC_CRLList* pIssuerCrl, |
132 | | const char* securityPolicyUri); |
133 | | |
134 | | static SOPC_ReturnStatus sopc_pki_merge_certificates(SOPC_CertificateList* pLeft, |
135 | | SOPC_CertificateList* pRight, |
136 | | SOPC_CertificateList** ppRes); |
137 | | |
138 | | static SOPC_ReturnStatus write_cert_to_der_files(SOPC_CertificateList* pRoots, |
139 | | SOPC_CertificateList* pCerts, |
140 | | const char* directoryPath, |
141 | | const bool bEraseExistingFiles); |
142 | | |
143 | | static SOPC_ReturnStatus write_crl_to_der_files(SOPC_CRLList* pCrl, |
144 | | const char* directoryPath, |
145 | | const bool bEraseExistingFiles); |
146 | | |
147 | | static SOPC_ReturnStatus may_create_pki_folder(const char* pBasePath, const char* pSubPath, char** ppPath); |
148 | | |
149 | | static bool ignore_filtered_file(const char* pFilePath); |
150 | | |
151 | | static SOPC_ReturnStatus load_certificate_or_crl_list(const char* basePath, |
152 | | SOPC_CertificateList** ppCerts, |
153 | | SOPC_CRLList** ppCrl, |
154 | | bool bIscrl, |
155 | | bool bDefaultBuild); |
156 | | |
157 | | static SOPC_ReturnStatus sopc_pki_load_certificate_and_crl_list_from_store(const char* basePath, |
158 | | SOPC_CertificateList** ppTrustedCerts, |
159 | | SOPC_CRLList** ppTrustedCrl, |
160 | | SOPC_CertificateList** ppIssuerCerts, |
161 | | SOPC_CRLList** ppIssuerCrl, |
162 | | bool bDefaultBuild); |
163 | | |
164 | | static bool pki_updated_trust_list_dir_exists(const char* path); |
165 | | |
166 | | static SOPC_ReturnStatus pki_create_from_store( |
167 | | const char* directoryStorePath, |
168 | | bool bDefaultBuild, /* If true load the root PKI directory without trust list update, |
169 | | if false try to load the updated trust list subdirectory.*/ |
170 | | SOPC_PKIProvider** ppPKI); |
171 | | |
172 | | static SOPC_ReturnStatus sopc_pki_merge_crls(SOPC_CRLList* pLeft, SOPC_CRLList* pRight, SOPC_CRLList** ppRes); |
173 | | |
174 | | static SOPC_ReturnStatus sopc_pki_remove_cert_by_thumbprint(SOPC_CertificateList** ppList, |
175 | | SOPC_CRLList** ppCRLList, |
176 | | const char* pThumbprint, |
177 | | const char* listName, |
178 | | bool* pbIsRemoved, |
179 | | bool* pbIsIssuer); |
180 | | |
181 | | static SOPC_ReturnStatus sopc_pki_check_lists(SOPC_CertificateList* pTrustedCerts, |
182 | | SOPC_CertificateList* pIssuerCerts, |
183 | | SOPC_CRLList* pTrustedCrl, |
184 | | SOPC_CRLList* pIssuerCrl, |
185 | | bool* bTrustedCaFound, |
186 | | bool* bIssuerCaFound); |
187 | | |
188 | | static SOPC_ReturnStatus sopc_pki_validate_anything(SOPC_PKIProvider* pPKI, |
189 | | const SOPC_CertificateList* pToValidate, |
190 | | const SOPC_PKI_Profile* pProfile, |
191 | | uint32_t* error); |
192 | | |
193 | | static SOPC_ReturnStatus sopc_pki_check_list_length(SOPC_PKIProvider* pPKI, |
194 | | SOPC_CertificateList* pTrustedCerts, |
195 | | SOPC_CRLList* pTrustedCrl, |
196 | | SOPC_CertificateList* pIssuerCerts, |
197 | | SOPC_CRLList* pIssuerCrl, |
198 | | const bool bIncludeExistingList); |
199 | | |
200 | | static SOPC_ReturnStatus sopc_pki_get_list_length(const SOPC_CertificateList* pTrustedCerts, |
201 | | const SOPC_CRLList* pTrustedCrl, |
202 | | const SOPC_CertificateList* pIssuerCerts, |
203 | | const SOPC_CRLList* pIssuerCrl, |
204 | | uint32_t* listLength); |
205 | | |
206 | | static const SOPC_PKI_ChainProfile* sopc_pki_get_chain_profile_from_security_policy(const char* uri); |
207 | | |
208 | | static const SOPC_PKI_LeafProfile* sopc_pki_get_leaf_profile_from_security_policy(const char* uri); |
209 | | |
210 | | /** |
211 | | * Static functions definition |
212 | | */ |
213 | | |
214 | | static void sopc_pki_clear(SOPC_PKIProvider* pPKI) |
215 | 0 | { |
216 | 0 | if (NULL == pPKI) |
217 | 0 | { |
218 | 0 | return; |
219 | 0 | } |
220 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
221 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
222 | | |
223 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pTrustedRoots); |
224 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pIssuerRoots); |
225 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pAllRoots); |
226 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pAllTrusted); |
227 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pTrustedCerts); |
228 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pIssuerCerts); |
229 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pAllCerts); |
230 | 0 | SOPC_KeyManager_CRL_Free(pPKI->pTrustedCrl); |
231 | 0 | SOPC_KeyManager_CRL_Free(pPKI->pIssuerCrl); |
232 | 0 | SOPC_KeyManager_CRL_Free(pPKI->pAllCrl); |
233 | 0 | SOPC_KeyManager_Certificate_Free(pPKI->pRejectedList); |
234 | 0 | SOPC_Free(pPKI->directoryStorePath); |
235 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
236 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
237 | 0 | mutStatus = SOPC_Mutex_Clear(&pPKI->mutex); |
238 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
239 | 0 | } |
240 | | |
241 | | // Copy newPKI content into currentPKI by preserving currentPKI mutex and then clear previous PKI content. |
242 | | // Then frees the new PKI structure. |
243 | | static void sopc_internal_replace_pki_and_clear(SOPC_PKIProvider* currentPKI, SOPC_PKIProvider** newPKI) |
244 | 0 | { |
245 | | // tmpPKI used for clear |
246 | 0 | SOPC_PKIProvider tmpPKI = *currentPKI; |
247 | 0 | tmpPKI.mutex = (*newPKI)->mutex; |
248 | | // Replace all except mutex which shall remain the same since PKI is already in use |
249 | 0 | currentPKI = memcpy(((char*) currentPKI) + sizeof(SOPC_Mutex), ((char*) (*newPKI)) + sizeof(SOPC_Mutex), |
250 | 0 | sizeof(SOPC_PKIProvider) - sizeof(SOPC_Mutex)); |
251 | | // clear previous PKI data and unused new PKI mutex |
252 | 0 | sopc_pki_clear(&tmpPKI); |
253 | | // frees unused new PKI structure |
254 | 0 | SOPC_Free(*newPKI); |
255 | 0 | *newPKI = NULL; |
256 | 0 | } |
257 | | |
258 | | static SOPC_ReturnStatus sopc_pki_check_application_uri(const SOPC_CertificateList* pToValidate, |
259 | | const char* applicationUri) |
260 | 0 | { |
261 | 0 | SOPC_ASSERT(NULL != pToValidate); |
262 | 0 | SOPC_ASSERT(NULL != applicationUri); |
263 | | |
264 | 0 | bool ok = SOPC_KeyManager_Certificate_CheckApplicationUri(pToValidate, applicationUri); |
265 | 0 | if (!ok) |
266 | 0 | { |
267 | 0 | char* pThumbprint = SOPC_KeyManager_Certificate_GetCstring_SHA1(pToValidate); |
268 | 0 | const char* thumbprint = NULL == pThumbprint ? "NULL" : pThumbprint; |
269 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, |
270 | 0 | "> PKI validation failed : the application URI %s is not stored in the URI SAN " |
271 | 0 | "extension of certificate thumbprint %s", |
272 | 0 | applicationUri, thumbprint); |
273 | 0 | SOPC_Free(pThumbprint); |
274 | 0 | return SOPC_STATUS_NOK; |
275 | 0 | } |
276 | 0 | return SOPC_STATUS_OK; |
277 | 0 | } |
278 | | |
279 | | static SOPC_ReturnStatus sopc_pki_check_security_level_of_the_update(const SOPC_CertificateList* pTrustedCerts, |
280 | | const SOPC_CRLList* pTrustedCrl, |
281 | | const SOPC_CertificateList* pIssuerCerts, |
282 | | const SOPC_CRLList* pIssuerCrl, |
283 | | const char* securityPolicyUri) |
284 | 0 | { |
285 | | /* |
286 | | TODO : |
287 | | |
288 | | -1 Add a way to configure the security level for each security policy uri (give them a weight) |
289 | | -2 For each certificate, retrieve their security policies from their properties. |
290 | | How to do it? The following issue has been SUBMITTED : https://mantis.opcfoundation.org/view.php?id=8976 |
291 | | */ |
292 | |
|
293 | 0 | SOPC_UNUSED_ARG(pTrustedCerts); |
294 | 0 | SOPC_UNUSED_ARG(pTrustedCrl); |
295 | 0 | SOPC_UNUSED_ARG(pIssuerCerts); |
296 | 0 | SOPC_UNUSED_ARG(pIssuerCrl); |
297 | 0 | SOPC_UNUSED_ARG(securityPolicyUri); |
298 | |
|
299 | 0 | return SOPC_STATUS_OK; |
300 | 0 | } |
301 | | |
302 | | static SOPC_ReturnStatus sopc_pki_merge_certificates(SOPC_CertificateList* pLeft, |
303 | | SOPC_CertificateList* pRight, |
304 | | SOPC_CertificateList** ppRes) |
305 | 0 | { |
306 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
307 | 0 | if (NULL == ppRes) |
308 | 0 | { |
309 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
310 | 0 | } |
311 | 0 | SOPC_CertificateList* pRes = *ppRes; |
312 | | /* Left part */ |
313 | 0 | if (NULL != pLeft) |
314 | 0 | { |
315 | 0 | status = SOPC_KeyManager_Certificate_Copy(pLeft, &pRes); |
316 | 0 | } |
317 | | /* Right part */ |
318 | 0 | if (NULL != pRight && SOPC_STATUS_OK == status) |
319 | 0 | { |
320 | 0 | status = SOPC_KeyManager_Certificate_Copy(pRight, &pRes); |
321 | 0 | } |
322 | | /* clear if error */ |
323 | 0 | if (SOPC_STATUS_OK != status) |
324 | 0 | { |
325 | 0 | SOPC_KeyManager_Certificate_Free(pRes); |
326 | 0 | pRes = NULL; |
327 | 0 | } |
328 | 0 | *ppRes = pRes; |
329 | 0 | return status; |
330 | 0 | } |
331 | | |
332 | | #if SOPC_HAS_FILESYSTEM |
333 | | static SOPC_ReturnStatus remove_files(const char* directoryPath) |
334 | 0 | { |
335 | 0 | SOPC_ASSERT(NULL != directoryPath); |
336 | | |
337 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
338 | 0 | SOPC_Array* pFilePaths = NULL; |
339 | 0 | char* pFilePath = NULL; |
340 | 0 | int res = -1; |
341 | | /* Get the array of file paths from the given directory */ |
342 | 0 | SOPC_FileSystem_GetDirResult dirRes = SOPC_FileSystem_GetDirFilePaths(directoryPath, &pFilePaths); |
343 | 0 | if (SOPC_FileSystem_GetDir_OK != dirRes) |
344 | 0 | { |
345 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, "> PKI write to store: failed to open directory <%s>.", |
346 | 0 | directoryPath); |
347 | 0 | return SOPC_STATUS_NOK; |
348 | 0 | } |
349 | 0 | size_t nbFiles = SOPC_Array_Size(pFilePaths); |
350 | 0 | for (size_t idx = 0; idx < nbFiles && SOPC_STATUS_OK == status; idx++) |
351 | 0 | { |
352 | 0 | pFilePath = SOPC_Array_Get(pFilePaths, char*, idx); |
353 | 0 | res = remove(pFilePath); |
354 | 0 | if (0 != res) |
355 | 0 | { |
356 | 0 | status = SOPC_STATUS_NOK; |
357 | 0 | } |
358 | 0 | } |
359 | 0 | SOPC_Array_Delete(pFilePaths); |
360 | 0 | return status; |
361 | 0 | } |
362 | | #else |
363 | | SOPC_ReturnStatus remove_files(const char* directoryPath) |
364 | | { |
365 | | SOPC_UNUSED_ARG(directoryPath); |
366 | | return SOPC_STATUS_NOT_SUPPORTED; |
367 | | } |
368 | | #endif /* SOPC_HAS_FILESYSTEM */ |
369 | | |
370 | | static SOPC_ReturnStatus write_cert_to_der_files(SOPC_CertificateList* pRoots, |
371 | | SOPC_CertificateList* pCerts, |
372 | | const char* directoryPath, |
373 | | const bool bEraseExistingFiles) |
374 | 0 | { |
375 | 0 | SOPC_ASSERT(NULL != directoryPath); |
376 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
377 | 0 | if (bEraseExistingFiles) |
378 | 0 | { |
379 | 0 | status = remove_files(directoryPath); |
380 | 0 | } |
381 | 0 | if (SOPC_STATUS_OK == status && NULL != pRoots) |
382 | 0 | { |
383 | 0 | status = SOPC_KeyManager_Certificate_ToDER_Files(pRoots, directoryPath); |
384 | 0 | } |
385 | 0 | if (SOPC_STATUS_OK == status && NULL != pCerts) |
386 | 0 | { |
387 | 0 | status = SOPC_KeyManager_Certificate_ToDER_Files(pCerts, directoryPath); |
388 | 0 | } |
389 | 0 | return status; |
390 | 0 | } |
391 | | |
392 | | static SOPC_ReturnStatus write_crl_to_der_files(SOPC_CRLList* pCrl, |
393 | | const char* directoryPath, |
394 | | const bool bEraseExistingFiles) |
395 | 0 | { |
396 | 0 | SOPC_ASSERT(NULL != directoryPath); |
397 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
398 | 0 | if (bEraseExistingFiles) |
399 | 0 | { |
400 | 0 | status = remove_files(directoryPath); |
401 | 0 | } |
402 | 0 | if (SOPC_STATUS_OK == status && NULL != pCrl) |
403 | 0 | { |
404 | 0 | status = SOPC_KeyManager_CRL_ToDER_Files(pCrl, directoryPath); |
405 | 0 | } |
406 | 0 | return status; |
407 | 0 | } |
408 | | |
409 | | static SOPC_ReturnStatus may_create_pki_folder(const char* pBasePath, const char* pSubPath, char** ppPath) |
410 | 0 | { |
411 | 0 | SOPC_FileSystem_CreationResult mkdir_res = SOPC_FileSystem_Creation_Error_UnknownIssue; |
412 | 0 | char* pPath = NULL; |
413 | 0 | SOPC_ReturnStatus status = SOPC_StrConcat(pBasePath, pSubPath, &pPath); |
414 | 0 | if (SOPC_STATUS_OK == status) |
415 | 0 | { |
416 | 0 | mkdir_res = SOPC_FileSystem_mkdir(pPath); |
417 | 0 | if (SOPC_FileSystem_Creation_Error_PathAlreadyExists != mkdir_res && SOPC_FileSystem_Creation_OK != mkdir_res) |
418 | 0 | { |
419 | 0 | status = SOPC_STATUS_NOK; |
420 | 0 | } |
421 | 0 | } |
422 | 0 | if (SOPC_STATUS_OK != status) |
423 | 0 | { |
424 | 0 | SOPC_Free(pPath); |
425 | 0 | pPath = NULL; |
426 | 0 | } |
427 | 0 | *ppPath = pPath; |
428 | 0 | return status; |
429 | 0 | } |
430 | | |
431 | | static bool ignore_filtered_file(const char* pFilePath) |
432 | 0 | { |
433 | 0 | char* lastSep = strrchr(pFilePath, '/'); |
434 | 0 | if (NULL != lastSep && '.' == lastSep[1]) |
435 | 0 | { |
436 | | // Ignore file if first file character is a dot '.' |
437 | 0 | return true; |
438 | 0 | } |
439 | 0 | return false; |
440 | 0 | } |
441 | | |
442 | | static SOPC_ReturnStatus load_certificate_or_crl_list(const char* basePath, |
443 | | SOPC_CertificateList** ppCerts, |
444 | | SOPC_CRLList** ppCrl, |
445 | | bool bIscrl, |
446 | | bool bDefaultBuild) |
447 | 0 | { |
448 | 0 | SOPC_ASSERT(NULL != basePath); |
449 | 0 | if (bIscrl) |
450 | 0 | { |
451 | 0 | SOPC_ASSERT(NULL != ppCrl && NULL == ppCerts); |
452 | 0 | } |
453 | 0 | else |
454 | 0 | { |
455 | 0 | SOPC_ASSERT(NULL == ppCrl && NULL != ppCerts); |
456 | 0 | } |
457 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
458 | 0 | SOPC_Array* pFilePaths = NULL; |
459 | 0 | SOPC_CertificateList* pCerts = NULL; |
460 | 0 | SOPC_CRLList* pCrl = NULL; |
461 | 0 | char* pFilePath = NULL; |
462 | | /* Get the array of path from basePath */ |
463 | 0 | SOPC_FileSystem_GetDirResult dirRes = SOPC_FileSystem_GetDirFilePaths(basePath, &pFilePaths); |
464 | 0 | if (SOPC_FileSystem_GetDir_OK != dirRes) |
465 | 0 | { |
466 | 0 | if (!bDefaultBuild) |
467 | 0 | { |
468 | 0 | SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_COMMON, "> PKI creation warning: failed to open directory <%s>.", |
469 | 0 | basePath); |
470 | 0 | } |
471 | 0 | else |
472 | 0 | { |
473 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, "> PKI creation error: failed to open directory <%s>.", |
474 | 0 | basePath); |
475 | 0 | } |
476 | 0 | return SOPC_STATUS_NOK; |
477 | 0 | } |
478 | | /* Get the size and iterate for each item */ |
479 | 0 | size_t nbFiles = SOPC_Array_Size(pFilePaths); |
480 | 0 | for (size_t idx = 0; idx < nbFiles && SOPC_STATUS_OK == status; idx++) |
481 | 0 | { |
482 | 0 | pFilePath = SOPC_Array_Get(pFilePaths, char*, idx); |
483 | 0 | if (ignore_filtered_file(pFilePath)) |
484 | 0 | { |
485 | 0 | SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_COMMON, "> PKI ignoring file <%s>", pFilePath); |
486 | 0 | } |
487 | 0 | else |
488 | 0 | { |
489 | 0 | SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_COMMON, "> PKI loading file <%s>", pFilePath); |
490 | |
|
491 | 0 | if (bIscrl) |
492 | 0 | { |
493 | | /* Load CRL */ |
494 | 0 | status = SOPC_KeyManager_CRL_CreateOrAddFromFile(pFilePath, &pCrl); |
495 | 0 | } |
496 | 0 | else |
497 | 0 | { |
498 | | /* Load CERT */ |
499 | 0 | status = SOPC_KeyManager_Certificate_CreateOrAddFromFile(pFilePath, &pCerts); |
500 | 0 | } |
501 | 0 | } |
502 | 0 | } |
503 | | /* Clear in case of error */ |
504 | 0 | if (SOPC_STATUS_OK != status) |
505 | 0 | { |
506 | 0 | SOPC_KeyManager_Certificate_Free(pCerts); |
507 | 0 | SOPC_KeyManager_CRL_Free(pCrl); |
508 | 0 | } |
509 | 0 | else |
510 | 0 | { |
511 | 0 | if (bIscrl) |
512 | 0 | { |
513 | 0 | *ppCrl = pCrl; |
514 | 0 | } |
515 | 0 | else |
516 | 0 | { |
517 | 0 | *ppCerts = pCerts; |
518 | 0 | } |
519 | 0 | } |
520 | | /* Always clear */ |
521 | 0 | SOPC_Array_Delete(pFilePaths); |
522 | 0 | return status; |
523 | 0 | } |
524 | | |
525 | | static SOPC_ReturnStatus sopc_pki_load_certificate_and_crl_list_from_store(const char* basePath, |
526 | | SOPC_CertificateList** ppTrustedCerts, |
527 | | SOPC_CRLList** ppTrustedCrl, |
528 | | SOPC_CertificateList** ppIssuerCerts, |
529 | | SOPC_CRLList** ppIssuerCrl, |
530 | | bool bDefaultBuild) |
531 | 0 | { |
532 | 0 | SOPC_ASSERT(NULL != basePath); |
533 | 0 | SOPC_ASSERT(NULL != ppTrustedCerts); |
534 | 0 | SOPC_ASSERT(NULL != ppTrustedCrl); |
535 | 0 | SOPC_ASSERT(NULL != ppIssuerCerts); |
536 | 0 | SOPC_ASSERT(NULL != ppIssuerCrl); |
537 | | /* Trusted Certs */ |
538 | 0 | char* trustedCertsPath = NULL; |
539 | 0 | SOPC_ReturnStatus status = SOPC_StrConcat(basePath, STR_TRUSTED_CERTS, &trustedCertsPath); |
540 | 0 | if (SOPC_STATUS_OK == status) |
541 | 0 | { |
542 | 0 | status = load_certificate_or_crl_list(trustedCertsPath, ppTrustedCerts, NULL, false, bDefaultBuild); |
543 | 0 | } |
544 | 0 | SOPC_Free(trustedCertsPath); |
545 | | /* Trusted Crl */ |
546 | 0 | if (SOPC_STATUS_OK == status) |
547 | 0 | { |
548 | 0 | char* trustedCrlPath = NULL; |
549 | 0 | status = SOPC_StrConcat(basePath, STR_TRUSTED_CRL, &trustedCrlPath); |
550 | 0 | if (SOPC_STATUS_OK == status) |
551 | 0 | { |
552 | 0 | status = load_certificate_or_crl_list(trustedCrlPath, NULL, ppTrustedCrl, true, bDefaultBuild); |
553 | 0 | } |
554 | 0 | SOPC_Free(trustedCrlPath); |
555 | 0 | } |
556 | | /* Issuer Certs */ |
557 | 0 | if (SOPC_STATUS_OK == status) |
558 | 0 | { |
559 | 0 | char* issuerCertsPath = NULL; |
560 | 0 | status = SOPC_StrConcat(basePath, STR_ISSUERS_CERTS, &issuerCertsPath); |
561 | 0 | if (SOPC_STATUS_OK == status) |
562 | 0 | { |
563 | 0 | status = load_certificate_or_crl_list(issuerCertsPath, ppIssuerCerts, NULL, false, bDefaultBuild); |
564 | 0 | } |
565 | 0 | SOPC_Free(issuerCertsPath); |
566 | 0 | } |
567 | | /* Issuer Crl */ |
568 | 0 | if (SOPC_STATUS_OK == status) |
569 | 0 | { |
570 | 0 | char* issuerCrlPath = NULL; |
571 | 0 | status = SOPC_StrConcat(basePath, STR_ISSUERS_CRL, &issuerCrlPath); |
572 | 0 | if (SOPC_STATUS_OK == status) |
573 | 0 | { |
574 | 0 | status = load_certificate_or_crl_list(issuerCrlPath, NULL, ppIssuerCrl, true, bDefaultBuild); |
575 | 0 | } |
576 | 0 | SOPC_Free(issuerCrlPath); |
577 | 0 | } |
578 | |
|
579 | 0 | if (SOPC_STATUS_OK != status) |
580 | 0 | { |
581 | 0 | SOPC_KeyManager_Certificate_Free(*ppTrustedCerts); |
582 | 0 | SOPC_KeyManager_Certificate_Free(*ppIssuerCerts); |
583 | 0 | SOPC_KeyManager_CRL_Free(*ppTrustedCrl); |
584 | 0 | SOPC_KeyManager_CRL_Free(*ppIssuerCrl); |
585 | 0 | *ppTrustedCerts = NULL; |
586 | 0 | *ppIssuerCerts = NULL; |
587 | 0 | *ppTrustedCrl = NULL; |
588 | 0 | *ppIssuerCrl = NULL; |
589 | 0 | } |
590 | 0 | return status; |
591 | 0 | } |
592 | | |
593 | | static bool pki_updated_trust_list_dir_exists(const char* path) |
594 | 0 | { |
595 | 0 | SOPC_Array* pFilePaths = NULL; |
596 | 0 | SOPC_FileSystem_GetDirResult dirRes = SOPC_FileSystem_GetDirFilePaths(path, &pFilePaths); |
597 | 0 | SOPC_Array_Delete(pFilePaths); |
598 | 0 | return (SOPC_FileSystem_GetDir_OK == dirRes); |
599 | 0 | } |
600 | | |
601 | | static SOPC_ReturnStatus pki_create_from_store( |
602 | | const char* directoryStorePath, |
603 | | bool bDefaultBuild, /* If true load the root PKI directory without trust list update, |
604 | | if false try to load the updated trust list subdirectory.*/ |
605 | | SOPC_PKIProvider** ppPKI) |
606 | 0 | { |
607 | 0 | SOPC_ASSERT(NULL != directoryStorePath); |
608 | 0 | SOPC_ASSERT(NULL != ppPKI); |
609 | | |
610 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
611 | 0 | SOPC_CertificateList* pTrustedCerts = NULL; /* trusted intermediate CA + trusted certificates */ |
612 | 0 | SOPC_CertificateList* pIssuerCerts = NULL; /* issuer intermediate CA */ |
613 | 0 | SOPC_CRLList* pTrustedCrl = NULL; /* CRLs of trusted intermediate CA and trusted root CA */ |
614 | 0 | SOPC_CRLList* pIssuerCrl = NULL; /* CRLs of issuer intermediate CA and issuer root CA */ |
615 | 0 | const char* basePath = NULL; |
616 | 0 | char* path = NULL; |
617 | 0 | char* trust_list_name = NULL; |
618 | | |
619 | | /* Select the right folder: add updateTrustList subdirectory path containing PKI update*/ |
620 | 0 | if (!bDefaultBuild) |
621 | 0 | { |
622 | 0 | status = SOPC_StrConcat(directoryStorePath, STR_TRUSTLIST_NAME, &path); |
623 | 0 | if (SOPC_STATUS_OK != status) |
624 | 0 | { |
625 | 0 | return status; |
626 | 0 | } |
627 | 0 | if (pki_updated_trust_list_dir_exists(path)) |
628 | 0 | { |
629 | 0 | basePath = path; |
630 | 0 | } |
631 | 0 | else |
632 | 0 | { |
633 | 0 | SOPC_Free(path); |
634 | 0 | path = NULL; |
635 | 0 | status = SOPC_STATUS_WOULD_BLOCK; |
636 | 0 | } |
637 | 0 | } |
638 | 0 | else |
639 | 0 | { |
640 | 0 | basePath = directoryStorePath; |
641 | 0 | } |
642 | | /* Load the files from the directory Store path */ |
643 | 0 | if (SOPC_STATUS_OK == status) |
644 | 0 | { |
645 | 0 | status = sopc_pki_load_certificate_and_crl_list_from_store(basePath, &pTrustedCerts, &pTrustedCrl, |
646 | 0 | &pIssuerCerts, &pIssuerCrl, bDefaultBuild); |
647 | 0 | } |
648 | | /* Check if the trustList is empty */ |
649 | 0 | if (SOPC_STATUS_OK == status && NULL == pTrustedCerts && NULL == pTrustedCrl && NULL == pIssuerCerts && |
650 | 0 | NULL == pIssuerCrl) |
651 | 0 | { |
652 | 0 | status = SOPC_STATUS_NOK; |
653 | 0 | if (!bDefaultBuild) |
654 | 0 | { |
655 | 0 | SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_COMMON, "> PKI creation warning: certificate store is empty (%s).", |
656 | 0 | path); |
657 | 0 | } |
658 | 0 | else |
659 | 0 | { |
660 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, "> PKI creation error: certificate store is empty (%s).", |
661 | 0 | path); |
662 | 0 | } |
663 | 0 | } |
664 | 0 | if (SOPC_STATUS_OK == status) |
665 | 0 | { |
666 | 0 | status = SOPC_PKIProvider_CreateFromList(pTrustedCerts, pTrustedCrl, pIssuerCerts, pIssuerCrl, ppPKI); |
667 | 0 | } |
668 | | /* if error then try with trusted and issuers folder. */ |
669 | 0 | if (!bDefaultBuild && SOPC_STATUS_OK != status) |
670 | 0 | { |
671 | 0 | SOPC_Logger_TraceInfo(SOPC_LOG_MODULE_COMMON, |
672 | 0 | "> PKI creation: loading PKI store root directory %s content (default behavior).", |
673 | 0 | directoryStorePath); |
674 | 0 | SOPC_Logger_TraceInfo(SOPC_LOG_MODULE_COMMON, |
675 | 0 | "> PKI creation: the updated PKI store subdirectory %s%s is absent" |
676 | 0 | " or its content cannot be loaded (see warnings in this case).", |
677 | 0 | directoryStorePath, STR_TRUSTLIST_NAME); |
678 | 0 | status = pki_create_from_store(directoryStorePath, true, ppPKI); |
679 | 0 | } |
680 | | /* Copy the directoryStorePath */ |
681 | 0 | if (SOPC_STATUS_OK == status) |
682 | 0 | { |
683 | | /* Copy only if not done during the recursive call. */ |
684 | 0 | if (NULL == (*ppPKI)->directoryStorePath) |
685 | 0 | { |
686 | 0 | (*ppPKI)->directoryStorePath = SOPC_strdup(directoryStorePath); |
687 | 0 | if (NULL == (*ppPKI)->directoryStorePath) |
688 | 0 | { |
689 | 0 | SOPC_PKIProvider_Free(ppPKI); |
690 | 0 | *ppPKI = NULL; |
691 | 0 | status = SOPC_STATUS_OUT_OF_MEMORY; |
692 | 0 | } |
693 | 0 | } |
694 | 0 | } |
695 | | |
696 | | /* Clear */ |
697 | 0 | SOPC_Free(path); |
698 | 0 | SOPC_Free(trust_list_name); |
699 | |
|
700 | 0 | SOPC_KeyManager_Certificate_Free(pTrustedCerts); |
701 | 0 | SOPC_KeyManager_Certificate_Free(pIssuerCerts); |
702 | 0 | SOPC_KeyManager_CRL_Free(pTrustedCrl); |
703 | 0 | SOPC_KeyManager_CRL_Free(pIssuerCrl); |
704 | |
|
705 | 0 | return status; |
706 | 0 | } |
707 | | |
708 | | static SOPC_ReturnStatus sopc_pki_get_list_length(const SOPC_CertificateList* pTrustedCerts, |
709 | | const SOPC_CRLList* pTrustedCrl, |
710 | | const SOPC_CertificateList* pIssuerCerts, |
711 | | const SOPC_CRLList* pIssuerCrl, |
712 | | uint32_t* listLength) |
713 | 0 | { |
714 | 0 | *listLength = 0; |
715 | 0 | size_t lenTrustedCerts = 0; |
716 | 0 | size_t lenTrustedCrl = 0; |
717 | 0 | size_t lenIssuerCerts = 0; |
718 | 0 | size_t lenIssuerCrl = 0; |
719 | 0 | size_t lenTot = 0; |
720 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
721 | 0 | if (NULL != pTrustedCerts) |
722 | 0 | { |
723 | 0 | status = SOPC_KeyManager_Certificate_GetListLength(pTrustedCerts, &lenTrustedCerts); |
724 | 0 | } |
725 | 0 | if (NULL != pTrustedCrl && SOPC_STATUS_OK == status) |
726 | 0 | { |
727 | 0 | status = SOPC_KeyManager_CRL_GetListLength(pTrustedCrl, &lenTrustedCrl); |
728 | 0 | } |
729 | 0 | if (NULL != pIssuerCerts && SOPC_STATUS_OK == status) |
730 | 0 | { |
731 | 0 | status = SOPC_KeyManager_Certificate_GetListLength(pIssuerCerts, &lenIssuerCerts); |
732 | 0 | } |
733 | 0 | if (NULL != pIssuerCrl && SOPC_STATUS_OK == status) |
734 | 0 | { |
735 | 0 | status = SOPC_KeyManager_CRL_GetListLength(pIssuerCrl, &lenIssuerCrl); |
736 | 0 | } |
737 | 0 | if (SOPC_STATUS_OK == status) |
738 | 0 | { |
739 | 0 | lenTot = lenTrustedCerts + lenTrustedCrl + lenIssuerCerts + lenIssuerCrl; |
740 | 0 | if (UINT32_MAX < lenTot) |
741 | 0 | { |
742 | 0 | status = SOPC_STATUS_INVALID_STATE; |
743 | 0 | } |
744 | 0 | else |
745 | 0 | { |
746 | 0 | *listLength = (uint32_t) lenTot; |
747 | 0 | } |
748 | 0 | } |
749 | 0 | return status; |
750 | 0 | } |
751 | | |
752 | | static SOPC_ReturnStatus sopc_pki_merge_crls(SOPC_CRLList* pLeft, SOPC_CRLList* pRight, SOPC_CRLList** ppRes) |
753 | 0 | { |
754 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
755 | 0 | if (NULL == ppRes) |
756 | 0 | { |
757 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
758 | 0 | } |
759 | 0 | SOPC_CRLList* pRes = *ppRes; |
760 | | /* Left part */ |
761 | 0 | if (NULL != pLeft) |
762 | 0 | { |
763 | 0 | status = SOPC_KeyManager_CRL_Copy(pLeft, &pRes); |
764 | 0 | } |
765 | | /* Right part */ |
766 | 0 | if (NULL != pRight && SOPC_STATUS_OK == status) |
767 | 0 | { |
768 | 0 | status = SOPC_KeyManager_CRL_Copy(pRight, &pRes); |
769 | 0 | } |
770 | | /* clear if error */ |
771 | 0 | if (SOPC_STATUS_OK != status) |
772 | 0 | { |
773 | 0 | SOPC_KeyManager_CRL_Free(pRes); |
774 | 0 | pRes = NULL; |
775 | 0 | } |
776 | 0 | *ppRes = pRes; |
777 | 0 | return status; |
778 | 0 | } |
779 | | |
780 | | static SOPC_ReturnStatus sopc_pki_remove_cert_by_thumbprint(SOPC_CertificateList** ppList, |
781 | | SOPC_CRLList** ppCRLList, |
782 | | const char* pThumbprint, |
783 | | const char* listName, |
784 | | bool* pbIsRemoved, |
785 | | bool* pbIsIssuer) |
786 | 0 | { |
787 | 0 | SOPC_ASSERT(NULL != ppList); |
788 | 0 | SOPC_ASSERT(NULL != ppCRLList); |
789 | 0 | SOPC_ASSERT(NULL != pThumbprint); |
790 | 0 | SOPC_ASSERT(NULL != pbIsRemoved); |
791 | 0 | SOPC_ASSERT(NULL != pbIsIssuer); |
792 | | |
793 | 0 | size_t lenThumb = strlen(pThumbprint); |
794 | 0 | SOPC_ASSERT(HEX_THUMBPRINT_SIZE == lenThumb); |
795 | | |
796 | | /* Initialized the value to return */ |
797 | 0 | *pbIsRemoved = false; |
798 | 0 | *pbIsIssuer = false; |
799 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
800 | |
|
801 | 0 | if (NULL == *ppList) |
802 | 0 | { |
803 | | /* the certificate list is empty, do nothing*/ |
804 | 0 | return SOPC_STATUS_OK; |
805 | 0 | } |
806 | | |
807 | 0 | uint32_t count = 0; |
808 | 0 | bool bIsIssuer = false; |
809 | 0 | bool bAtLeastOneIssuer = false; |
810 | 0 | bool bAtLeastOne = false; |
811 | |
|
812 | 0 | bool bCertIsRemoved = true; |
813 | 0 | while (bCertIsRemoved && SOPC_STATUS_OK == status) |
814 | 0 | { |
815 | 0 | status = SOPC_KeyManager_CertificateList_RemoveCertFromSHA1(ppList, ppCRLList, pThumbprint, &bCertIsRemoved, |
816 | 0 | &bIsIssuer); |
817 | 0 | if (bCertIsRemoved) |
818 | 0 | { |
819 | 0 | if (bIsIssuer) |
820 | 0 | { |
821 | 0 | bAtLeastOneIssuer = true; |
822 | 0 | } |
823 | 0 | if (bAtLeastOneIssuer && !bIsIssuer) |
824 | 0 | { |
825 | 0 | SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_COMMON, |
826 | 0 | "> PKI remove: certificate thumbprint <%s> has been found both as CA and as " |
827 | 0 | "leaf certificate from %s", |
828 | 0 | pThumbprint, listName); |
829 | 0 | } |
830 | 0 | bAtLeastOne = true; |
831 | 0 | count = count + 1; |
832 | 0 | } |
833 | 0 | } |
834 | |
|
835 | 0 | if (bAtLeastOne && NULL != listName) |
836 | 0 | { |
837 | 0 | SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_COMMON, |
838 | 0 | "> PKI remove: certificate thumbprint <%s> has been removed (%" PRIu32 " times) from %s", |
839 | 0 | pThumbprint, count, listName); |
840 | 0 | } |
841 | |
|
842 | 0 | *pbIsIssuer = bAtLeastOneIssuer; |
843 | 0 | *pbIsRemoved = bAtLeastOne; |
844 | 0 | return status; |
845 | 0 | } |
846 | | |
847 | | static SOPC_ReturnStatus sopc_pki_check_lists(SOPC_CertificateList* pTrustedCerts, |
848 | | SOPC_CertificateList* pIssuerCerts, |
849 | | SOPC_CRLList* pTrustedCrl, |
850 | | SOPC_CRLList* pIssuerCrl, |
851 | | bool* bTrustedCaFound, |
852 | | bool* bIssuerCaFound) |
853 | 0 | { |
854 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
855 | | /* Trusted stats */ |
856 | 0 | uint32_t trusted_ca_count = 0; |
857 | 0 | uint32_t trusted_list_length = 0; |
858 | 0 | uint32_t issued_cert_count = 0; |
859 | 0 | uint32_t trusted_root_count = 0; |
860 | | /* Issuer stats */ |
861 | 0 | uint32_t issuer_ca_count = 0; |
862 | 0 | uint32_t issuer_list_length = 0; |
863 | 0 | uint32_t issuer_root_count = 0; |
864 | 0 | *bTrustedCaFound = false; |
865 | 0 | *bIssuerCaFound = false; |
866 | |
|
867 | 0 | if (NULL == pTrustedCerts) |
868 | 0 | { |
869 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, "> PKI creation error: no trusted certificate is provided."); |
870 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
871 | 0 | } |
872 | 0 | SOPC_PKIProviderInternal_GetListStats(pTrustedCerts, &trusted_ca_count, &trusted_list_length, &trusted_root_count); |
873 | 0 | issued_cert_count = trusted_list_length - trusted_ca_count; |
874 | | /* trusted CA => trusted CRL*/ |
875 | 0 | if (0 != trusted_ca_count && NULL == pTrustedCrl) |
876 | 0 | { |
877 | 0 | SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_COMMON, |
878 | 0 | "> PKI creation warning: trusted CA certificates are provided but no CRL."); |
879 | 0 | } |
880 | 0 | SOPC_PKIProviderInternal_GetListStats(pIssuerCerts, &issuer_ca_count, &issuer_list_length, &issuer_root_count); |
881 | | /* issuer CA => issuer CRL*/ |
882 | 0 | if (0 != issuer_ca_count && NULL == pIssuerCrl) |
883 | 0 | { |
884 | 0 | SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_COMMON, |
885 | 0 | "> PKI creation warning: issuer CA certificates are provided but no CRL."); |
886 | 0 | } |
887 | | /* Check if issuerCerts list is only filled with CA. */ |
888 | 0 | if (issuer_list_length != issuer_ca_count) |
889 | 0 | { |
890 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, "> PKI creation error: not all issuer certificates are CAs."); |
891 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
892 | 0 | } |
893 | | /* check and warn in case no roots is provided wheras at least one trusted leaf certificate is provided. */ |
894 | 0 | if ((0 == issuer_root_count) && (0 == trusted_root_count) && (0 != issued_cert_count)) |
895 | 0 | { |
896 | | /* In this case, only trusted self-signed leaf certificates will be accepted. */ |
897 | 0 | SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_COMMON, |
898 | 0 | "> PKI creation warning: no root (CA) defined: only trusted self-signed leaf " |
899 | 0 | "certificates will be accepted without possibility to revoke them (no CRL)."); |
900 | 0 | } |
901 | 0 | *bTrustedCaFound = 0 != trusted_ca_count; |
902 | 0 | *bIssuerCaFound = 0 != issuer_ca_count; |
903 | 0 | return status; |
904 | 0 | } |
905 | | |
906 | | static SOPC_ReturnStatus sopc_pki_check_list_length(SOPC_PKIProvider* pPKI, |
907 | | SOPC_CertificateList* pTrustedCerts, |
908 | | SOPC_CRLList* pTrustedCrl, |
909 | | SOPC_CertificateList* pIssuerCerts, |
910 | | SOPC_CRLList* pIssuerCrl, |
911 | | const bool bIncludeExistingList) |
912 | 0 | { |
913 | 0 | SOPC_ASSERT(NULL != pPKI); |
914 | 0 | uint32_t PKILen = 0; |
915 | 0 | uint32_t updateLen = 0; |
916 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
917 | 0 | if (bIncludeExistingList) |
918 | 0 | { |
919 | 0 | status = sopc_pki_get_list_length(pPKI->pTrustedCerts, pPKI->pTrustedCrl, pPKI->pIssuerCerts, pPKI->pIssuerCrl, |
920 | 0 | &PKILen); |
921 | 0 | } |
922 | 0 | if (SOPC_STATUS_OK == status) |
923 | 0 | { |
924 | 0 | status = sopc_pki_get_list_length(pTrustedCerts, pTrustedCrl, pIssuerCerts, pIssuerCrl, &updateLen); |
925 | 0 | } |
926 | 0 | if (SOPC_STATUS_OK != status) |
927 | 0 | { |
928 | 0 | return status; |
929 | 0 | } |
930 | 0 | if (SOPC_PKI_MAX_NB_CERT_AND_CRL < PKILen + updateLen) |
931 | 0 | { |
932 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, |
933 | 0 | "> PKI creation error: too many (%" PRIu32 |
934 | 0 | ") certificates and CRLs. The maximum configured is %" PRIu32 |
935 | 0 | ", please change SOPC_PKI_MAX_NB_CERT_AND_CRL", |
936 | 0 | PKILen + updateLen, (uint32_t) SOPC_PKI_MAX_NB_CERT_AND_CRL); |
937 | 0 | } |
938 | 0 | return status; |
939 | 0 | } |
940 | | |
941 | | static SOPC_ReturnStatus sopc_pki_validate_anything(SOPC_PKIProvider* pPKI, |
942 | | const SOPC_CertificateList* pToValidate, |
943 | | const SOPC_PKI_Profile* pProfile, |
944 | | uint32_t* error) |
945 | 0 | { |
946 | 0 | SOPC_UNUSED_ARG(pPKI); |
947 | 0 | SOPC_UNUSED_ARG(pToValidate); |
948 | 0 | SOPC_UNUSED_ARG(pProfile); |
949 | 0 | SOPC_UNUSED_ARG(error); |
950 | 0 | return SOPC_STATUS_OK; |
951 | 0 | } |
952 | | |
953 | 0 | #define NB_PROFILES (sizeof(g_all_profiles) / sizeof(*g_all_profiles)) |
954 | | |
955 | | static const SOPC_PKI_ChainProfile* sopc_pki_get_chain_profile_from_security_policy(const char* uri) |
956 | 0 | { |
957 | 0 | if (NULL == uri) |
958 | 0 | { |
959 | 0 | return NULL; |
960 | 0 | } |
961 | | |
962 | 0 | const size_t len = strlen(uri) + 1; |
963 | 0 | for (size_t i = 0; i < NB_PROFILES; ++i) |
964 | 0 | { |
965 | 0 | const struct Profile_Cfg* pProfile = &g_all_profiles[i]; |
966 | 0 | const SOPC_SecurityPolicy_Config* pPolicy = SOPC_SecurityPolicy_Config_Get(pProfile->id); |
967 | 0 | const char* pUri = pPolicy->uri; |
968 | 0 | if (pUri != NULL && SOPC_strncmp_ignore_case(uri, pUri, len) == 0) |
969 | 0 | { |
970 | 0 | return pProfile->chain; |
971 | 0 | } |
972 | 0 | } |
973 | | |
974 | 0 | return NULL; |
975 | 0 | } |
976 | | |
977 | | static const SOPC_PKI_LeafProfile* sopc_pki_get_leaf_profile_from_security_policy(const char* uri) |
978 | 0 | { |
979 | 0 | if (NULL == uri) |
980 | 0 | { |
981 | 0 | return NULL; |
982 | 0 | } |
983 | | |
984 | 0 | const size_t len = strlen(uri) + 1; |
985 | 0 | for (size_t i = 0; i < NB_PROFILES; ++i) |
986 | 0 | { |
987 | 0 | const struct Profile_Cfg* pProfile = &g_all_profiles[i]; |
988 | 0 | const SOPC_SecurityPolicy_Config* pPolicy = SOPC_SecurityPolicy_Config_Get(pProfile->id); |
989 | 0 | const char* pUri = pPolicy->uri; |
990 | 0 | if (pUri != NULL && SOPC_strncmp_ignore_case(uri, pUri, len) == 0) |
991 | 0 | { |
992 | 0 | return pProfile->leaf; |
993 | 0 | } |
994 | 0 | } |
995 | 0 | return NULL; |
996 | 0 | } |
997 | | |
998 | | #endif /* WITH_NO_CRYPTO */ |
999 | | |
1000 | | /** |
1001 | | * End of static functions definition |
1002 | | * |
1003 | | */ |
1004 | | |
1005 | | SOPC_ReturnStatus SOPC_PKIProvider_CreateLeafProfile(const char* securityPolicyUri, SOPC_PKI_LeafProfile** ppProfile) |
1006 | 0 | { |
1007 | | #ifdef WITH_NO_CRYPTO |
1008 | | SOPC_UNUSED_ARG(securityPolicyUri); |
1009 | | SOPC_UNUSED_ARG(ppProfile); |
1010 | | return SOPC_STATUS_NOT_SUPPORTED; |
1011 | | #else |
1012 | 0 | if (NULL == ppProfile) |
1013 | 0 | { |
1014 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1015 | 0 | } |
1016 | 0 | const SOPC_PKI_LeafProfile* pProfileRef = NULL; |
1017 | 0 | if (NULL != securityPolicyUri) |
1018 | 0 | { |
1019 | 0 | pProfileRef = sopc_pki_get_leaf_profile_from_security_policy(securityPolicyUri); |
1020 | 0 | if (NULL == pProfileRef) |
1021 | 0 | { |
1022 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1023 | 0 | } |
1024 | 0 | } |
1025 | 0 | SOPC_PKI_LeafProfile* pProfile = SOPC_Calloc(1, sizeof(SOPC_PKI_LeafProfile)); |
1026 | 0 | if (NULL == pProfile) |
1027 | 0 | { |
1028 | 0 | return SOPC_STATUS_OUT_OF_MEMORY; |
1029 | 0 | } |
1030 | | |
1031 | 0 | if (NULL != securityPolicyUri) |
1032 | 0 | { |
1033 | 0 | *pProfile = *pProfileRef; |
1034 | 0 | } |
1035 | |
|
1036 | 0 | *ppProfile = pProfile; |
1037 | 0 | return SOPC_STATUS_OK; |
1038 | 0 | #endif |
1039 | 0 | } |
1040 | | |
1041 | | SOPC_ReturnStatus SOPC_PKIProvider_LeafProfileSetUsageFromType(SOPC_PKI_LeafProfile* pProfile, SOPC_PKI_Type PKIType) |
1042 | 0 | { |
1043 | | #ifdef WITH_NO_CRYPTO |
1044 | | SOPC_UNUSED_ARG(pProfile); |
1045 | | SOPC_UNUSED_ARG(PKIType); |
1046 | | return SOPC_STATUS_NOT_SUPPORTED; |
1047 | | #else |
1048 | 0 | if (NULL == pProfile) |
1049 | 0 | { |
1050 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1051 | 0 | } |
1052 | 0 | switch (PKIType) |
1053 | 0 | { |
1054 | 0 | case SOPC_PKI_TYPE_CLIENT_APP: |
1055 | 0 | pProfile->keyUsage = g_appKU; |
1056 | 0 | pProfile->extendedKeyUsage = g_clientEKU; |
1057 | 0 | break; |
1058 | 0 | case SOPC_PKI_TYPE_SERVER_APP: |
1059 | 0 | pProfile->keyUsage = g_appKU; |
1060 | 0 | pProfile->extendedKeyUsage = g_serverEKU; |
1061 | 0 | break; |
1062 | 0 | case SOPC_PKI_TYPE_USER: |
1063 | 0 | pProfile->keyUsage = g_usrKU; |
1064 | 0 | pProfile->extendedKeyUsage = g_userEKU; |
1065 | 0 | break; |
1066 | 0 | default: |
1067 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1068 | 0 | } |
1069 | 0 | return SOPC_STATUS_OK; |
1070 | 0 | #endif |
1071 | 0 | } |
1072 | | |
1073 | | SOPC_ReturnStatus SOPC_PKIProvider_LeafProfileSetURI(SOPC_PKI_LeafProfile* pProfile, const char* applicationUri) |
1074 | 0 | { |
1075 | | #ifdef WITH_NO_CRYPTO |
1076 | | SOPC_UNUSED_ARG(pProfile); |
1077 | | SOPC_UNUSED_ARG(applicationUri); |
1078 | | return SOPC_STATUS_NOT_SUPPORTED; |
1079 | | #else |
1080 | 0 | if (NULL == pProfile || NULL == applicationUri) |
1081 | 0 | { |
1082 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1083 | 0 | } |
1084 | 0 | if (NULL != pProfile->sanApplicationUri) |
1085 | 0 | { |
1086 | 0 | return SOPC_STATUS_INVALID_STATE; |
1087 | 0 | } |
1088 | 0 | pProfile->sanApplicationUri = SOPC_strdup(applicationUri); |
1089 | 0 | if (NULL == pProfile->sanApplicationUri) |
1090 | 0 | { |
1091 | 0 | return SOPC_STATUS_OUT_OF_MEMORY; |
1092 | 0 | } |
1093 | 0 | return SOPC_STATUS_OK; |
1094 | 0 | #endif |
1095 | 0 | } |
1096 | | |
1097 | | SOPC_ReturnStatus SOPC_PKIProvider_LeafProfileSetURL(SOPC_PKI_LeafProfile* pProfile, const char* url) |
1098 | 0 | { |
1099 | | #ifdef WITH_NO_CRYPTO |
1100 | | SOPC_UNUSED_ARG(pProfile); |
1101 | | SOPC_UNUSED_ARG(url); |
1102 | | return SOPC_STATUS_NOT_SUPPORTED; |
1103 | | #else |
1104 | 0 | if (NULL == pProfile || NULL == url) |
1105 | 0 | { |
1106 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1107 | 0 | } |
1108 | 0 | if (NULL != pProfile->sanURL) |
1109 | 0 | { |
1110 | 0 | return SOPC_STATUS_INVALID_STATE; |
1111 | 0 | } |
1112 | 0 | pProfile->sanURL = SOPC_strdup(url); |
1113 | 0 | if (NULL == pProfile->sanURL) |
1114 | 0 | { |
1115 | 0 | return SOPC_STATUS_OUT_OF_MEMORY; |
1116 | 0 | } |
1117 | 0 | return SOPC_STATUS_OK; |
1118 | 0 | #endif |
1119 | 0 | } |
1120 | | |
1121 | | SOPC_ReturnStatus SOPC_PKIProvider_ProfileSetURI(SOPC_PKI_Profile* pProfile, const char* applicationUri) |
1122 | 0 | { |
1123 | 0 | return SOPC_PKIProvider_LeafProfileSetURI(pProfile->leafProfile, applicationUri); |
1124 | 0 | } |
1125 | | |
1126 | | SOPC_ReturnStatus SOPC_PKIProvider_ProfileSetURL(SOPC_PKI_Profile* pProfile, const char* url) |
1127 | 0 | { |
1128 | 0 | return SOPC_PKIProvider_LeafProfileSetURL(pProfile->leafProfile, url); |
1129 | 0 | } |
1130 | | |
1131 | | void SOPC_PKIProvider_DeleteLeafProfile(SOPC_PKI_LeafProfile** ppProfile) |
1132 | 0 | { |
1133 | | #ifdef WITH_NO_CRYPTO |
1134 | | SOPC_UNUSED_ARG(ppProfile); |
1135 | | #else |
1136 | 0 | if (NULL == ppProfile) |
1137 | 0 | { |
1138 | 0 | return; |
1139 | 0 | } |
1140 | 0 | SOPC_PKI_LeafProfile* pProfile = *ppProfile; |
1141 | 0 | if (NULL != pProfile) |
1142 | 0 | { |
1143 | 0 | SOPC_Free(pProfile->sanApplicationUri); |
1144 | 0 | SOPC_Free(pProfile->sanURL); |
1145 | 0 | SOPC_Free(pProfile); |
1146 | 0 | *ppProfile = NULL; |
1147 | 0 | } |
1148 | 0 | #endif |
1149 | 0 | } |
1150 | | |
1151 | | SOPC_ReturnStatus SOPC_PKIProvider_CreateProfile(const char* securityPolicyUri, SOPC_PKI_Profile** ppProfile) |
1152 | 0 | { |
1153 | | #ifdef WITH_NO_CRYPTO |
1154 | | SOPC_UNUSED_ARG(securityPolicyUri); |
1155 | | SOPC_UNUSED_ARG(ppProfile); |
1156 | | return SOPC_STATUS_NOT_SUPPORTED; |
1157 | | #else |
1158 | 0 | if (NULL == ppProfile || NULL == securityPolicyUri) |
1159 | 0 | { |
1160 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1161 | 0 | } |
1162 | 0 | const SOPC_PKI_ChainProfile* pChainProfileRef = sopc_pki_get_chain_profile_from_security_policy(securityPolicyUri); |
1163 | 0 | if (NULL == pChainProfileRef) |
1164 | 0 | { |
1165 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1166 | 0 | } |
1167 | 0 | SOPC_PKI_ChainProfile* pChainProfile = SOPC_Calloc(1, sizeof(SOPC_PKI_ChainProfile)); |
1168 | 0 | if (NULL == pChainProfile) |
1169 | 0 | { |
1170 | 0 | return SOPC_STATUS_OUT_OF_MEMORY; |
1171 | 0 | } |
1172 | 0 | *pChainProfile = *pChainProfileRef; |
1173 | |
|
1174 | 0 | SOPC_PKI_LeafProfile* pLeafProfile = NULL; |
1175 | 0 | SOPC_PKI_Profile* pProfile = NULL; |
1176 | 0 | SOPC_ReturnStatus status = SOPC_PKIProvider_CreateLeafProfile(securityPolicyUri, &pLeafProfile); |
1177 | 0 | if (SOPC_STATUS_OK == status) |
1178 | 0 | { |
1179 | 0 | pProfile = SOPC_Calloc(1, sizeof(SOPC_PKI_Profile)); |
1180 | 0 | if (NULL == pProfile) |
1181 | 0 | { |
1182 | 0 | status = SOPC_STATUS_OUT_OF_MEMORY; |
1183 | 0 | } |
1184 | 0 | } |
1185 | 0 | if (SOPC_STATUS_OK == status) |
1186 | 0 | { |
1187 | 0 | pProfile->leafProfile = pLeafProfile; |
1188 | 0 | pProfile->chainProfile = pChainProfile; |
1189 | 0 | pProfile->bBackwardInteroperability = true; |
1190 | 0 | pProfile->bApplyLeafProfile = true; |
1191 | 0 | } |
1192 | 0 | else |
1193 | 0 | { |
1194 | 0 | SOPC_Free(pChainProfile); |
1195 | 0 | SOPC_PKIProvider_DeleteLeafProfile(&pLeafProfile); |
1196 | 0 | } |
1197 | 0 | *ppProfile = pProfile; |
1198 | 0 | return SOPC_STATUS_OK; |
1199 | 0 | #endif |
1200 | 0 | } |
1201 | | |
1202 | | SOPC_ReturnStatus SOPC_PKIProvider_ProfileSetUsageFromType(SOPC_PKI_Profile* pProfile, SOPC_PKI_Type PKIType) |
1203 | 0 | { |
1204 | | #ifdef WITH_NO_CRYPTO |
1205 | | SOPC_UNUSED_ARG(pProfile); |
1206 | | SOPC_UNUSED_ARG(PKIType); |
1207 | | return SOPC_STATUS_NOT_SUPPORTED; |
1208 | | #else |
1209 | 0 | if (NULL == pProfile) |
1210 | 0 | { |
1211 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1212 | 0 | } |
1213 | 0 | SOPC_ReturnStatus status = SOPC_PKIProvider_LeafProfileSetUsageFromType(pProfile->leafProfile, PKIType); |
1214 | 0 | if (SOPC_STATUS_OK != status) |
1215 | 0 | { |
1216 | 0 | return status; |
1217 | 0 | } |
1218 | 0 | switch (PKIType) |
1219 | 0 | { |
1220 | 0 | case SOPC_PKI_TYPE_CLIENT_APP: |
1221 | 0 | pProfile->bApplyLeafProfile = true; |
1222 | 0 | pProfile->bBackwardInteroperability = true; |
1223 | 0 | break; |
1224 | 0 | case SOPC_PKI_TYPE_SERVER_APP: |
1225 | 0 | pProfile->bApplyLeafProfile = true; |
1226 | 0 | pProfile->bBackwardInteroperability = true; |
1227 | 0 | break; |
1228 | 0 | case SOPC_PKI_TYPE_USER: |
1229 | 0 | pProfile->bApplyLeafProfile = false; |
1230 | 0 | pProfile->bBackwardInteroperability = false; |
1231 | 0 | break; |
1232 | 0 | default: |
1233 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1234 | 0 | } |
1235 | 0 | return SOPC_STATUS_OK; |
1236 | 0 | #endif |
1237 | 0 | } |
1238 | | |
1239 | | void SOPC_PKIProvider_DeleteProfile(SOPC_PKI_Profile** ppProfile) |
1240 | 0 | { |
1241 | | #ifdef WITH_NO_CRYPTO |
1242 | | SOPC_UNUSED_ARG(ppProfile); |
1243 | | #else |
1244 | 0 | if (NULL == ppProfile) |
1245 | 0 | { |
1246 | 0 | return; |
1247 | 0 | } |
1248 | 0 | SOPC_PKI_Profile* pProfile = *ppProfile; |
1249 | 0 | if (NULL != pProfile) |
1250 | 0 | { |
1251 | 0 | SOPC_Free(pProfile->chainProfile); |
1252 | 0 | SOPC_PKIProvider_DeleteLeafProfile(&pProfile->leafProfile); |
1253 | 0 | SOPC_Free(pProfile); |
1254 | 0 | *ppProfile = NULL; |
1255 | 0 | } |
1256 | 0 | #endif |
1257 | 0 | } |
1258 | | |
1259 | | SOPC_ReturnStatus SOPC_PKIProvider_CreateMinimalUserProfile(SOPC_PKI_Profile** ppProfile) |
1260 | 0 | { |
1261 | | #ifdef WITH_NO_CRYPTO |
1262 | | SOPC_UNUSED_ARG(ppProfile); |
1263 | | return SOPC_STATUS_NOT_SUPPORTED; |
1264 | | #else |
1265 | | /* Minimal profile for the chain. |
1266 | | The leaf profile is not used for users during the validation process but the user certificate properties |
1267 | | are checked according to the security policy during the activate session */ |
1268 | 0 | if (NULL == ppProfile) |
1269 | 0 | { |
1270 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1271 | 0 | } |
1272 | 0 | SOPC_PKI_Profile* pProfile = NULL; |
1273 | 0 | SOPC_ReturnStatus status = SOPC_PKIProvider_CreateProfile(SOPC_SecurityPolicy_Basic256Sha256_URI, &pProfile); |
1274 | 0 | if (SOPC_STATUS_OK == status) |
1275 | 0 | { |
1276 | 0 | status = SOPC_PKIProvider_ProfileSetUsageFromType(pProfile, SOPC_PKI_TYPE_USER); |
1277 | 0 | } |
1278 | 0 | *ppProfile = pProfile; |
1279 | 0 | return status; |
1280 | 0 | #endif |
1281 | 0 | } |
1282 | | |
1283 | | SOPC_ReturnStatus SOPC_PKIProvider_CheckLeafCertificate(const SOPC_CertificateList* pToValidate, |
1284 | | const SOPC_PKI_LeafProfile* pProfile, |
1285 | | uint32_t* error) |
1286 | 0 | { |
1287 | | #ifdef WITH_NO_CRYPTO |
1288 | | SOPC_UNUSED_ARG(pToValidate); |
1289 | | SOPC_UNUSED_ARG(pProfile); |
1290 | | SOPC_UNUSED_ARG(error); |
1291 | | return SOPC_STATUS_NOT_SUPPORTED; |
1292 | | #else |
1293 | 0 | if (NULL == pToValidate || NULL == pProfile || NULL == error) |
1294 | 0 | { |
1295 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1296 | 0 | } |
1297 | | |
1298 | 0 | *error = SOPC_CertificateValidationError_Unknown; |
1299 | 0 | uint32_t firstError = SOPC_CertificateValidationError_Unknown; |
1300 | 0 | uint32_t currentError = SOPC_CertificateValidationError_Unknown; |
1301 | 0 | bool bErrorFound = false; |
1302 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1303 | 0 | status = SOPC_PKIProvider_CheckCommonName(pToValidate); |
1304 | 0 | if (SOPC_STATUS_OK != status) |
1305 | 0 | { |
1306 | 0 | firstError = SOPC_CertificateValidationError_Invalid; |
1307 | 0 | bErrorFound = true; |
1308 | 0 | } |
1309 | 0 | if (pProfile->bApplySecurityPolicy) |
1310 | 0 | { |
1311 | 0 | status = SOPC_PKIProvider_CheckSecurityPolicy(pToValidate, pProfile); |
1312 | 0 | if (SOPC_STATUS_OK != status) |
1313 | 0 | { |
1314 | 0 | currentError = SOPC_CertificateValidationError_PolicyCheckFailed; |
1315 | 0 | if (!bErrorFound) |
1316 | 0 | { |
1317 | 0 | firstError = currentError; |
1318 | 0 | bErrorFound = true; |
1319 | 0 | } |
1320 | 0 | } |
1321 | 0 | } |
1322 | 0 | if (NULL != pProfile->sanURL) |
1323 | 0 | { |
1324 | 0 | status = SOPC_PKIProvider_CheckHostName(pToValidate, pProfile->sanURL); |
1325 | 0 | if (SOPC_STATUS_OK != status) |
1326 | 0 | { |
1327 | 0 | currentError = SOPC_CertificateValidationError_HostNameInvalid; |
1328 | 0 | if (!bErrorFound) |
1329 | 0 | { |
1330 | 0 | firstError = currentError; |
1331 | 0 | bErrorFound = true; |
1332 | 0 | } |
1333 | 0 | } |
1334 | 0 | } |
1335 | 0 | if (NULL != pProfile->sanApplicationUri) |
1336 | 0 | { |
1337 | 0 | status = sopc_pki_check_application_uri(pToValidate, pProfile->sanApplicationUri); |
1338 | 0 | if (SOPC_STATUS_OK != status) |
1339 | 0 | { |
1340 | 0 | currentError = SOPC_CertificateValidationError_UriInvalid; |
1341 | 0 | if (!bErrorFound) |
1342 | 0 | { |
1343 | 0 | firstError = currentError; |
1344 | 0 | bErrorFound = true; |
1345 | 0 | } |
1346 | 0 | } |
1347 | 0 | } |
1348 | 0 | status = SOPC_PKIProvider_CheckCertificateUsage(pToValidate, pProfile); |
1349 | 0 | if (SOPC_STATUS_OK != status) |
1350 | 0 | { |
1351 | 0 | currentError = SOPC_CertificateValidationError_UseNotAllowed; |
1352 | 0 | if (!bErrorFound) |
1353 | 0 | { |
1354 | 0 | firstError = currentError; |
1355 | 0 | bErrorFound = true; |
1356 | 0 | } |
1357 | 0 | } |
1358 | |
|
1359 | 0 | if (bErrorFound) |
1360 | 0 | { |
1361 | 0 | *error = firstError; |
1362 | 0 | status = SOPC_STATUS_NOK; |
1363 | 0 | } |
1364 | |
|
1365 | 0 | return status; |
1366 | 0 | #endif |
1367 | 0 | } |
1368 | | |
1369 | | SOPC_ReturnStatus SOPC_PKIPermissive_Create(SOPC_PKIProvider** ppPKI) |
1370 | 0 | { |
1371 | | #ifdef WITH_NO_CRYPTO |
1372 | | SOPC_UNUSED_ARG(ppPKI); |
1373 | | return SOPC_STATUS_NOT_SUPPORTED; |
1374 | | #else |
1375 | 0 | SOPC_PKIProvider* pPKI = NULL; |
1376 | |
|
1377 | 0 | if (NULL == ppPKI) |
1378 | 0 | { |
1379 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1380 | 0 | } |
1381 | | |
1382 | 0 | pPKI = SOPC_Calloc(1, sizeof(SOPC_PKIProvider)); |
1383 | |
|
1384 | 0 | if (NULL == pPKI) |
1385 | 0 | { |
1386 | 0 | return SOPC_STATUS_OUT_OF_MEMORY; |
1387 | 0 | } |
1388 | | |
1389 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Initialization(&pPKI->mutex); |
1390 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1391 | 0 | pPKI->pTrustedRoots = NULL; |
1392 | 0 | pPKI->pTrustedCerts = NULL; |
1393 | 0 | pPKI->pTrustedCrl = NULL; |
1394 | 0 | pPKI->pIssuerRoots = NULL; |
1395 | 0 | pPKI->pIssuerCerts = NULL; |
1396 | 0 | pPKI->pIssuerCrl = NULL; |
1397 | 0 | pPKI->pAllCerts = NULL; |
1398 | 0 | pPKI->pAllRoots = NULL; |
1399 | 0 | pPKI->pAllCrl = NULL; |
1400 | 0 | pPKI->pRejectedList = NULL; |
1401 | 0 | pPKI->directoryStorePath = NULL; |
1402 | 0 | pPKI->pFnValidateCert = &sopc_pki_validate_anything; |
1403 | 0 | pPKI->pUpdateCb = NULL; |
1404 | 0 | pPKI->updateCbParam = 0; |
1405 | 0 | pPKI->isPermissive = true; |
1406 | 0 | *ppPKI = pPKI; |
1407 | 0 | return SOPC_STATUS_OK; |
1408 | 0 | #endif |
1409 | 0 | } |
1410 | | |
1411 | | void SOPC_PKIProvider_Free(SOPC_PKIProvider** ppPKI) |
1412 | 0 | { |
1413 | | #ifdef WITH_NO_CRYPTO |
1414 | | SOPC_UNUSED_ARG(ppPKI); |
1415 | | #else |
1416 | 0 | if (NULL == ppPKI || NULL == *ppPKI) |
1417 | 0 | { |
1418 | 0 | return; |
1419 | 0 | } |
1420 | 0 | sopc_pki_clear(*ppPKI); |
1421 | 0 | SOPC_Free(*ppPKI); |
1422 | 0 | *ppPKI = NULL; |
1423 | 0 | #endif |
1424 | 0 | } |
1425 | | |
1426 | | SOPC_ReturnStatus SOPC_PKIProvider_SetStorePath(const char* directoryStorePath, SOPC_PKIProvider* pPKI) |
1427 | 0 | { |
1428 | | #ifdef WITH_NO_CRYPTO |
1429 | | SOPC_UNUSED_ARG(directoryStorePath); |
1430 | | SOPC_UNUSED_ARG(pPKI); |
1431 | | return SOPC_STATUS_NOT_SUPPORTED; |
1432 | | #else |
1433 | 0 | if (NULL == pPKI || NULL == directoryStorePath) |
1434 | 0 | { |
1435 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1436 | 0 | } |
1437 | | |
1438 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1439 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1440 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1441 | | |
1442 | | /* Create if necessary the store */ |
1443 | 0 | SOPC_FileSystem_CreationResult mkdir_res = SOPC_FileSystem_mkdir(directoryStorePath); |
1444 | 0 | if (SOPC_FileSystem_Creation_Error_PathAlreadyExists != mkdir_res && SOPC_FileSystem_Creation_OK != mkdir_res) |
1445 | 0 | { |
1446 | 0 | status = SOPC_STATUS_INVALID_PARAMETERS; |
1447 | 0 | } |
1448 | |
|
1449 | 0 | if (SOPC_STATUS_OK == status) |
1450 | 0 | { |
1451 | | /* Copy the directory store path before exchange the data */ |
1452 | 0 | char* pCopyPath = SOPC_strdup(directoryStorePath); |
1453 | 0 | if (NULL == pCopyPath) |
1454 | 0 | { |
1455 | 0 | status = SOPC_STATUS_NOK; |
1456 | 0 | } |
1457 | 0 | SOPC_Free(pPKI->directoryStorePath); |
1458 | 0 | pPKI->directoryStorePath = pCopyPath; |
1459 | 0 | } |
1460 | |
|
1461 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
1462 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1463 | | |
1464 | 0 | return status; |
1465 | 0 | #endif |
1466 | 0 | } |
1467 | | |
1468 | | SOPC_ReturnStatus SOPC_PKIProvider_SetUpdateCb(SOPC_PKIProvider* pPKI, |
1469 | | SOPC_PKIProviderUpdateCb* pUpdateCb, |
1470 | | uintptr_t updateParam) |
1471 | 0 | { |
1472 | | #ifdef WITH_NO_CRYPTO |
1473 | | SOPC_UNUSED_ARG(pPKI); |
1474 | | SOPC_UNUSED_ARG(pUpdateCb); |
1475 | | SOPC_UNUSED_ARG(updateParam); |
1476 | | return SOPC_STATUS_NOT_SUPPORTED; |
1477 | | #else |
1478 | 0 | if (NULL == pPKI || NULL == pUpdateCb) |
1479 | 0 | { |
1480 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1481 | 0 | } |
1482 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_STATE; |
1483 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1484 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1485 | 0 | if (NULL == pPKI->pUpdateCb) |
1486 | 0 | { |
1487 | 0 | pPKI->pUpdateCb = pUpdateCb; |
1488 | 0 | pPKI->updateCbParam = updateParam; |
1489 | 0 | status = SOPC_STATUS_OK; |
1490 | 0 | } |
1491 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
1492 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1493 | 0 | return status; |
1494 | 0 | #endif |
1495 | 0 | } |
1496 | | |
1497 | | SOPC_ReturnStatus SOPC_PKIProvider_WriteOrAppendToList(SOPC_PKIProvider* pPKI, |
1498 | | SOPC_CertificateList** ppTrustedCerts, |
1499 | | SOPC_CRLList** ppTrustedCrl, |
1500 | | SOPC_CertificateList** ppIssuerCerts, |
1501 | | SOPC_CRLList** ppIssuerCrl) |
1502 | 0 | { |
1503 | | #ifdef WITH_NO_CRYPTO |
1504 | | SOPC_UNUSED_ARG(pPKI); |
1505 | | SOPC_UNUSED_ARG(ppTrustedCerts); |
1506 | | SOPC_UNUSED_ARG(ppTrustedCrl); |
1507 | | SOPC_UNUSED_ARG(ppIssuerCerts); |
1508 | | SOPC_UNUSED_ARG(ppIssuerCrl); |
1509 | | return SOPC_STATUS_NOT_SUPPORTED; |
1510 | | #else |
1511 | 0 | if (NULL == pPKI || NULL == ppTrustedCerts || NULL == ppTrustedCrl || NULL == ppIssuerCerts || NULL == ppIssuerCrl) |
1512 | 0 | { |
1513 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1514 | 0 | } |
1515 | | |
1516 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1517 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1518 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1519 | | |
1520 | 0 | SOPC_CertificateList* pTrustedCerts = *ppTrustedCerts; |
1521 | 0 | SOPC_CRLList* pTrustedCrl = *ppTrustedCrl; |
1522 | 0 | SOPC_CertificateList* pIssuerCerts = *ppIssuerCerts; |
1523 | 0 | SOPC_CRLList* pIssuerCrl = *ppIssuerCrl; |
1524 | |
|
1525 | 0 | status = sopc_pki_merge_certificates(pPKI->pTrustedRoots, pPKI->pTrustedCerts, &pTrustedCerts); |
1526 | 0 | if (SOPC_STATUS_OK == status && NULL != pPKI->pTrustedCrl) |
1527 | 0 | { |
1528 | 0 | status = SOPC_KeyManager_CRL_Copy(pPKI->pTrustedCrl, &pTrustedCrl); |
1529 | 0 | } |
1530 | 0 | if (SOPC_STATUS_OK == status) |
1531 | 0 | { |
1532 | 0 | status = sopc_pki_merge_certificates(pPKI->pIssuerRoots, pPKI->pIssuerCerts, &pIssuerCerts); |
1533 | 0 | } |
1534 | 0 | if (SOPC_STATUS_OK == status && NULL != pPKI->pIssuerCrl) |
1535 | 0 | { |
1536 | 0 | status = SOPC_KeyManager_CRL_Copy(pPKI->pIssuerCrl, &pIssuerCrl); |
1537 | 0 | } |
1538 | | /* Clear if error */ |
1539 | 0 | if (SOPC_STATUS_OK != status) |
1540 | 0 | { |
1541 | 0 | SOPC_KeyManager_Certificate_Free(pTrustedCerts); |
1542 | 0 | SOPC_KeyManager_Certificate_Free(pIssuerCerts); |
1543 | 0 | SOPC_KeyManager_CRL_Free(pTrustedCrl); |
1544 | 0 | SOPC_KeyManager_CRL_Free(pIssuerCrl); |
1545 | 0 | pTrustedCerts = NULL; |
1546 | 0 | pIssuerCerts = NULL; |
1547 | 0 | pTrustedCrl = NULL; |
1548 | 0 | pIssuerCrl = NULL; |
1549 | 0 | } |
1550 | 0 | *ppTrustedCerts = pTrustedCerts; |
1551 | 0 | *ppIssuerCerts = pIssuerCerts; |
1552 | 0 | *ppTrustedCrl = pTrustedCrl; |
1553 | 0 | *ppIssuerCrl = pIssuerCrl; |
1554 | |
|
1555 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
1556 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1557 | | |
1558 | 0 | return status; |
1559 | 0 | #endif |
1560 | 0 | } |
1561 | | |
1562 | | SOPC_ReturnStatus SOPC_PKIProvider_WriteToStore(SOPC_PKIProvider* pPKI, const bool bEraseExistingFiles) |
1563 | 0 | { |
1564 | | #ifdef WITH_NO_CRYPTO |
1565 | | SOPC_UNUSED_ARG(bEraseExistingFiles); |
1566 | | SOPC_UNUSED_ARG(pPKI); |
1567 | | return SOPC_STATUS_NOT_SUPPORTED; |
1568 | | #else |
1569 | 0 | if (NULL == pPKI) |
1570 | 0 | { |
1571 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1572 | 0 | } |
1573 | 0 | char* basePath = NULL; |
1574 | 0 | char* path = NULL; |
1575 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1576 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1577 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1578 | | |
1579 | | /* The case of the PKI is built from buffer (there is no store) */ |
1580 | 0 | if (NULL == pPKI->directoryStorePath) |
1581 | 0 | { |
1582 | 0 | status = SOPC_STATUS_INVALID_STATE; |
1583 | 0 | } |
1584 | |
|
1585 | 0 | if (SOPC_STATUS_OK == status) |
1586 | 0 | { |
1587 | 0 | status = may_create_pki_folder(pPKI->directoryStorePath, STR_TRUSTLIST_NAME, &basePath); |
1588 | 0 | } |
1589 | 0 | if (SOPC_STATUS_OK == status) |
1590 | 0 | { |
1591 | 0 | status = may_create_pki_folder(basePath, STR_TRUSTED, &path); |
1592 | 0 | } |
1593 | 0 | if (SOPC_STATUS_OK == status) |
1594 | 0 | { |
1595 | 0 | SOPC_Free(path); |
1596 | 0 | status = may_create_pki_folder(basePath, STR_TRUSTED_CERTS, &path); |
1597 | 0 | } |
1598 | 0 | if (SOPC_STATUS_OK == status) |
1599 | 0 | { |
1600 | | // Note: might use pPKI->pAllTrusted instead which is equivalent to the merged list |
1601 | 0 | status = write_cert_to_der_files(pPKI->pTrustedRoots, pPKI->pTrustedCerts, path, bEraseExistingFiles); |
1602 | 0 | } |
1603 | 0 | if (SOPC_STATUS_OK == status) |
1604 | 0 | { |
1605 | 0 | SOPC_Free(path); |
1606 | 0 | status = may_create_pki_folder(basePath, STR_TRUSTED_CRL, &path); |
1607 | 0 | } |
1608 | 0 | if (SOPC_STATUS_OK == status) |
1609 | 0 | { |
1610 | 0 | status = write_crl_to_der_files(pPKI->pTrustedCrl, path, bEraseExistingFiles); |
1611 | 0 | } |
1612 | 0 | if (SOPC_STATUS_OK == status) |
1613 | 0 | { |
1614 | 0 | SOPC_Free(path); |
1615 | 0 | status = may_create_pki_folder(basePath, STR_ISSUERS, &path); |
1616 | 0 | } |
1617 | 0 | if (SOPC_STATUS_OK == status) |
1618 | 0 | { |
1619 | 0 | SOPC_Free(path); |
1620 | 0 | status = may_create_pki_folder(basePath, STR_ISSUERS_CERTS, &path); |
1621 | 0 | } |
1622 | 0 | if (SOPC_STATUS_OK == status) |
1623 | 0 | { |
1624 | 0 | status = write_cert_to_der_files(pPKI->pIssuerRoots, pPKI->pIssuerCerts, path, bEraseExistingFiles); |
1625 | 0 | } |
1626 | 0 | if (SOPC_STATUS_OK == status) |
1627 | 0 | { |
1628 | 0 | SOPC_Free(path); |
1629 | 0 | status = may_create_pki_folder(basePath, STR_ISSUERS_CRL, &path); |
1630 | 0 | } |
1631 | 0 | if (SOPC_STATUS_OK == status) |
1632 | 0 | { |
1633 | 0 | status = write_crl_to_der_files(pPKI->pIssuerCrl, path, bEraseExistingFiles); |
1634 | 0 | } |
1635 | |
|
1636 | 0 | SOPC_Free(basePath); |
1637 | 0 | SOPC_Free(path); |
1638 | |
|
1639 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
1640 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1641 | | |
1642 | 0 | return status; |
1643 | 0 | #endif |
1644 | 0 | } |
1645 | | |
1646 | | SOPC_ReturnStatus SOPC_PKIProvider_CopyRejectedList(SOPC_PKIProvider* pPKI, SOPC_CertificateList** ppCert) |
1647 | 0 | { |
1648 | | #ifdef WITH_NO_CRYPTO |
1649 | | SOPC_UNUSED_ARG(ppCert); |
1650 | | SOPC_UNUSED_ARG(pPKI); |
1651 | | return SOPC_STATUS_NOT_SUPPORTED; |
1652 | | #else |
1653 | 0 | if (NULL == pPKI || NULL == ppCert) |
1654 | 0 | { |
1655 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1656 | 0 | } |
1657 | | |
1658 | 0 | SOPC_CertificateList* pRejected = NULL; |
1659 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1660 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1661 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1662 | | |
1663 | 0 | if (NULL != pPKI->pRejectedList) |
1664 | 0 | { |
1665 | 0 | status = SOPC_KeyManager_Certificate_Copy(pPKI->pRejectedList, &pRejected); |
1666 | 0 | } |
1667 | | /* Clear */ |
1668 | 0 | if (SOPC_STATUS_OK != status) |
1669 | 0 | { |
1670 | 0 | SOPC_KeyManager_Certificate_Free(pRejected); |
1671 | 0 | pRejected = NULL; |
1672 | 0 | } |
1673 | 0 | *ppCert = pRejected; |
1674 | |
|
1675 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
1676 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1677 | | |
1678 | 0 | return status; |
1679 | 0 | #endif |
1680 | 0 | } |
1681 | | |
1682 | | SOPC_ReturnStatus SOPC_PKIProvider_WriteRejectedCertToStore(SOPC_PKIProvider* pPKI) |
1683 | 0 | { |
1684 | | #ifdef WITH_NO_CRYPTO |
1685 | | SOPC_UNUSED_ARG(pPKI); |
1686 | | return SOPC_STATUS_NOT_SUPPORTED; |
1687 | | #else |
1688 | 0 | if (NULL == pPKI) |
1689 | 0 | { |
1690 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1691 | 0 | } |
1692 | 0 | char* path = NULL; |
1693 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1694 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1695 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1696 | | |
1697 | | /* The case of the PKI is built from buffer (there is no store) */ |
1698 | 0 | if (NULL == pPKI->directoryStorePath) |
1699 | 0 | { |
1700 | 0 | status = SOPC_STATUS_INVALID_STATE; |
1701 | 0 | } |
1702 | 0 | if (SOPC_STATUS_OK == status) |
1703 | 0 | { |
1704 | 0 | status = may_create_pki_folder(pPKI->directoryStorePath, STR_REJECTED, &path); |
1705 | 0 | if (SOPC_STATUS_OK == status) |
1706 | 0 | { |
1707 | 0 | status = remove_files(path); |
1708 | 0 | } |
1709 | 0 | } |
1710 | 0 | if (SOPC_STATUS_OK == status && NULL != pPKI->pRejectedList) |
1711 | 0 | { |
1712 | 0 | status = SOPC_KeyManager_Certificate_ToDER_Files(pPKI->pRejectedList, path); |
1713 | 0 | } |
1714 | 0 | SOPC_Free(path); |
1715 | |
|
1716 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
1717 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1718 | | |
1719 | 0 | return status; |
1720 | 0 | #endif |
1721 | 0 | } |
1722 | | |
1723 | | SOPC_ReturnStatus SOPC_PKIProvider_UpdateFromList(SOPC_PKIProvider* pPKI, |
1724 | | const char* securityPolicyUri, |
1725 | | SOPC_CertificateList* pTrustedCerts, |
1726 | | SOPC_CRLList* pTrustedCrl, |
1727 | | SOPC_CertificateList* pIssuerCerts, |
1728 | | SOPC_CRLList* pIssuerCrl, |
1729 | | const bool bIncludeExistingList) |
1730 | 0 | { |
1731 | | #ifdef WITH_NO_CRYPTO |
1732 | | SOPC_UNUSED_ARG(pPKI); |
1733 | | SOPC_UNUSED_ARG(securityPolicyUri); |
1734 | | SOPC_UNUSED_ARG(pTrustedCerts); |
1735 | | SOPC_UNUSED_ARG(pTrustedCrl); |
1736 | | SOPC_UNUSED_ARG(pIssuerCerts); |
1737 | | SOPC_UNUSED_ARG(pIssuerCrl); |
1738 | | SOPC_UNUSED_ARG(bIncludeExistingList); |
1739 | | return SOPC_STATUS_NOT_SUPPORTED; |
1740 | | #else |
1741 | | /* Check parameters */ |
1742 | 0 | if (NULL == pPKI) |
1743 | 0 | { |
1744 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1745 | 0 | } |
1746 | 0 | if (NULL == pPKI->pUpdateCb) |
1747 | 0 | { |
1748 | 0 | return SOPC_STATUS_INVALID_STATE; |
1749 | 0 | } |
1750 | | |
1751 | 0 | SOPC_PKIProvider* pTmpPKI = NULL; |
1752 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1753 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1754 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1755 | | |
1756 | | /* Check the number of certificates plus CRLs */ |
1757 | 0 | status = |
1758 | 0 | sopc_pki_check_list_length(pPKI, pTrustedCerts, pTrustedCrl, pIssuerCerts, pIssuerCrl, bIncludeExistingList); |
1759 | | |
1760 | | /* Handle that the security level of the update isn't higher than the |
1761 | | security level of the secure channel. (§7.3.4 part 2 v1.05) */ |
1762 | 0 | if (SOPC_STATUS_OK == status) |
1763 | 0 | { |
1764 | 0 | status = sopc_pki_check_security_level_of_the_update(pTrustedCerts, pTrustedCrl, pIssuerCerts, pIssuerCrl, |
1765 | 0 | securityPolicyUri); |
1766 | 0 | } |
1767 | |
|
1768 | 0 | if (SOPC_STATUS_OK == status) |
1769 | 0 | { |
1770 | | /* Includes the existing TrustList plus any updates */ |
1771 | 0 | if (bIncludeExistingList && !pPKI->isPermissive) |
1772 | 0 | { |
1773 | 0 | SOPC_CertificateList* tmp_pTrustedCerts = NULL; /* trusted intermediate CA + trusted certificates */ |
1774 | 0 | SOPC_CertificateList* tmp_pTrustedCertsTmp = NULL; |
1775 | 0 | SOPC_CRLList* tmp_pTrustedCrl = NULL; /* CRLs of trusted intermediate CA and trusted root CA */ |
1776 | 0 | SOPC_CertificateList* tmp_pIssuerCerts = NULL; /* issuer intermediate CA + issuer root CA */ |
1777 | 0 | SOPC_CertificateList* tmp_pIssuerCertsTmp = NULL; |
1778 | 0 | SOPC_CRLList* tmp_pIssuerCrl = NULL; /* CRLs of issuer intermediate CA and issuer root CA */ |
1779 | | |
1780 | | /* tmp_pTrustedCerts = pTrustedCerts + pPKI->pTrustedCerts + pPKI->pTrustedRoot */ |
1781 | 0 | status = sopc_pki_merge_certificates(pPKI->pTrustedCerts, pTrustedCerts, &tmp_pTrustedCertsTmp); |
1782 | 0 | if (SOPC_STATUS_OK == status) |
1783 | 0 | { |
1784 | 0 | status = sopc_pki_merge_certificates(pPKI->pTrustedRoots, tmp_pTrustedCertsTmp, &tmp_pTrustedCerts); |
1785 | 0 | } |
1786 | | /* tmp_pTrustedCrl = pTrustedCrl + pPKI->pTrustedCrl */ |
1787 | 0 | if (SOPC_STATUS_OK == status) |
1788 | 0 | { |
1789 | 0 | status = sopc_pki_merge_crls(pPKI->pTrustedCrl, pTrustedCrl, &tmp_pTrustedCrl); |
1790 | 0 | } |
1791 | | /* tmp_pIssuerCerts = pIssuerCerts + pPKI->pIssuerCerts + pPKI->pIssuerRoot */ |
1792 | 0 | if (SOPC_STATUS_OK == status) |
1793 | 0 | { |
1794 | 0 | status = sopc_pki_merge_certificates(pPKI->pIssuerCerts, pIssuerCerts, &tmp_pIssuerCertsTmp); |
1795 | 0 | } |
1796 | 0 | if (SOPC_STATUS_OK == status) |
1797 | 0 | { |
1798 | 0 | status = sopc_pki_merge_certificates(pPKI->pIssuerRoots, tmp_pIssuerCertsTmp, &tmp_pIssuerCerts); |
1799 | 0 | } |
1800 | | /* tmp_pIssuerCrl = pIssuerCrl + pPKI->pIssuerCrl */ |
1801 | 0 | if (SOPC_STATUS_OK == status) |
1802 | 0 | { |
1803 | 0 | status = sopc_pki_merge_crls(pPKI->pIssuerCrl, pIssuerCrl, &tmp_pIssuerCrl); |
1804 | 0 | } |
1805 | | /* Create a new tmp PKI */ |
1806 | 0 | if (SOPC_STATUS_OK == status) |
1807 | 0 | { |
1808 | 0 | status = SOPC_PKIProvider_CreateFromList(tmp_pTrustedCerts, tmp_pTrustedCrl, tmp_pIssuerCerts, |
1809 | 0 | tmp_pIssuerCrl, &pTmpPKI); |
1810 | 0 | } |
1811 | |
|
1812 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pTrustedCerts); |
1813 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pTrustedCertsTmp); |
1814 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pIssuerCerts); |
1815 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pIssuerCertsTmp); |
1816 | 0 | SOPC_KeyManager_CRL_Free(tmp_pTrustedCrl); |
1817 | 0 | SOPC_KeyManager_CRL_Free(tmp_pIssuerCrl); |
1818 | 0 | } |
1819 | 0 | else |
1820 | 0 | { |
1821 | | /* Create a new tmp PKI without the existing TrustList */ |
1822 | 0 | status = SOPC_PKIProvider_CreateFromList(pTrustedCerts, pTrustedCrl, pIssuerCerts, pIssuerCrl, &pTmpPKI); |
1823 | 0 | } |
1824 | 0 | } |
1825 | | /* Copy the rejected list before exchange the data */ |
1826 | 0 | if (SOPC_STATUS_OK == status && NULL != pPKI->pRejectedList) |
1827 | 0 | { |
1828 | 0 | status = SOPC_KeyManager_Certificate_Copy(pPKI->pRejectedList, &pTmpPKI->pRejectedList); |
1829 | 0 | } |
1830 | | /* Copy the directory store path before exchange the data */ |
1831 | 0 | if (SOPC_STATUS_OK == status && NULL != pPKI->directoryStorePath) |
1832 | 0 | { |
1833 | 0 | pTmpPKI->directoryStorePath = SOPC_strdup(pPKI->directoryStorePath); |
1834 | 0 | if (NULL == pTmpPKI->directoryStorePath) |
1835 | 0 | { |
1836 | 0 | status = SOPC_STATUS_OUT_OF_MEMORY; |
1837 | 0 | } |
1838 | 0 | } |
1839 | | |
1840 | | /* Copy callback pointer and param before exchange the data */ |
1841 | 0 | if (SOPC_STATUS_OK == status) |
1842 | 0 | { |
1843 | 0 | pTmpPKI->pUpdateCb = pPKI->pUpdateCb; |
1844 | 0 | pTmpPKI->updateCbParam = pPKI->updateCbParam; |
1845 | 0 | } |
1846 | | |
1847 | | // Exchange the internal data between tmpPKI and PKI, clear previous data and free tmpPKI structure |
1848 | | // Note: mutex is kept since PKI should already be in use |
1849 | 0 | if (SOPC_STATUS_OK == status) |
1850 | 0 | { |
1851 | 0 | sopc_internal_replace_pki_and_clear(pPKI, &pTmpPKI); |
1852 | 0 | } |
1853 | | |
1854 | | // In case of failure we need to clear and free the temporary PKI |
1855 | 0 | if (NULL != pTmpPKI) |
1856 | 0 | { |
1857 | 0 | sopc_pki_clear(pTmpPKI); |
1858 | 0 | SOPC_Free(pTmpPKI); |
1859 | 0 | pTmpPKI = NULL; |
1860 | 0 | } |
1861 | |
|
1862 | 0 | if (SOPC_STATUS_OK == status) |
1863 | 0 | { |
1864 | 0 | pPKI->pUpdateCb(pPKI->updateCbParam); |
1865 | 0 | } |
1866 | | |
1867 | | // Unlock PKI prior to possibly clearing it |
1868 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
1869 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1870 | | |
1871 | 0 | return status; |
1872 | 0 | #endif |
1873 | 0 | } |
1874 | | |
1875 | | SOPC_ReturnStatus SOPC_PKIProvider_RemoveCertificate(SOPC_PKIProvider* pPKI, |
1876 | | const char* pThumbprint, |
1877 | | const bool bIsTrusted, |
1878 | | bool* pIsRemoved, |
1879 | | bool* pIsIssuer) |
1880 | 0 | { |
1881 | | #ifdef WITH_NO_CRYPTO |
1882 | | SOPC_UNUSED_ARG(pPKI); |
1883 | | SOPC_UNUSED_ARG(pThumbprint); |
1884 | | SOPC_UNUSED_ARG(bIsTrusted); |
1885 | | SOPC_UNUSED_ARG(pIsRemoved); |
1886 | | SOPC_UNUSED_ARG(pIsIssuer); |
1887 | | return SOPC_STATUS_NOT_SUPPORTED; |
1888 | | #else |
1889 | | /* Initialized the value to return */ |
1890 | 0 | *pIsRemoved = false; |
1891 | 0 | *pIsIssuer = false; |
1892 | 0 | if (NULL == pPKI || NULL == pThumbprint) |
1893 | 0 | { |
1894 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1895 | 0 | } |
1896 | 0 | if (NULL == pPKI->pUpdateCb) |
1897 | 0 | { |
1898 | 0 | return SOPC_STATUS_INVALID_STATE; |
1899 | 0 | } |
1900 | | |
1901 | 0 | size_t lenThumbprint = strlen(pThumbprint); |
1902 | 0 | if (HEX_THUMBPRINT_SIZE != lenThumbprint) |
1903 | 0 | { |
1904 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
1905 | 0 | } |
1906 | | |
1907 | 0 | bool bRootIsRemoved = false; |
1908 | 0 | bool bCertIsRemoved = false; |
1909 | 0 | bool bCertIsCA = false; |
1910 | 0 | bool bRootIsCA = false; |
1911 | |
|
1912 | 0 | bool bIsIssuer = false; |
1913 | 0 | bool bIsRemoved = false; |
1914 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
1915 | |
|
1916 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
1917 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
1918 | | |
1919 | | /* Remove from trusted certificates */ |
1920 | 0 | if (bIsTrusted) |
1921 | 0 | { |
1922 | 0 | if (NULL != pPKI->pTrustedCerts) |
1923 | 0 | { |
1924 | 0 | status = sopc_pki_remove_cert_by_thumbprint(&pPKI->pTrustedCerts, &pPKI->pTrustedCrl, pThumbprint, |
1925 | 0 | "trusted list", &bCertIsRemoved, &bCertIsCA); |
1926 | 0 | } |
1927 | 0 | if (NULL != pPKI->pTrustedRoots && SOPC_STATUS_OK == status) |
1928 | 0 | { |
1929 | 0 | status = sopc_pki_remove_cert_by_thumbprint(&pPKI->pTrustedRoots, &pPKI->pTrustedCrl, pThumbprint, |
1930 | 0 | "trusted root list", &bRootIsRemoved, &bRootIsCA); |
1931 | 0 | SOPC_ASSERT(SOPC_STATUS_OK != status || bRootIsCA == bRootIsRemoved); |
1932 | 0 | } |
1933 | 0 | if (NULL != pPKI->pAllTrusted && SOPC_STATUS_OK == status) |
1934 | 0 | { |
1935 | 0 | bool bAllTrustedRemoved = false; |
1936 | 0 | bool bAllTrustedIsCA = false; |
1937 | 0 | status = sopc_pki_remove_cert_by_thumbprint(&pPKI->pAllTrusted, &pPKI->pTrustedCrl, pThumbprint, NULL, |
1938 | 0 | &bAllTrustedRemoved, &bAllTrustedIsCA); |
1939 | 0 | SOPC_ASSERT(SOPC_STATUS_OK != status || (bAllTrustedRemoved == (bRootIsRemoved || bCertIsRemoved) && |
1940 | 0 | (bAllTrustedIsCA == (bCertIsCA || bRootIsCA)))); |
1941 | 0 | } |
1942 | 0 | } |
1943 | 0 | else |
1944 | 0 | { |
1945 | | /* Remove from issuer certificates */ |
1946 | 0 | if (NULL != pPKI->pIssuerCerts) |
1947 | 0 | { |
1948 | 0 | status = sopc_pki_remove_cert_by_thumbprint(&pPKI->pIssuerCerts, &pPKI->pIssuerCrl, pThumbprint, |
1949 | 0 | "issuer list", &bCertIsRemoved, &bCertIsCA); |
1950 | 0 | SOPC_ASSERT(SOPC_STATUS_OK != status || bCertIsCA == bCertIsRemoved); |
1951 | 0 | } |
1952 | 0 | if (NULL != pPKI->pIssuerRoots && SOPC_STATUS_OK == status) |
1953 | 0 | { |
1954 | 0 | status = sopc_pki_remove_cert_by_thumbprint(&pPKI->pIssuerRoots, &pPKI->pIssuerCrl, pThumbprint, |
1955 | 0 | "issuer root list", &bRootIsRemoved, &bRootIsCA); |
1956 | 0 | SOPC_ASSERT(SOPC_STATUS_OK != status || bRootIsCA == bRootIsRemoved); |
1957 | 0 | } |
1958 | 0 | } |
1959 | 0 | if (SOPC_STATUS_OK == status) |
1960 | 0 | { |
1961 | 0 | if (bCertIsRemoved || bRootIsRemoved) |
1962 | 0 | { |
1963 | 0 | bIsIssuer = bCertIsCA || bRootIsCA; |
1964 | 0 | bIsRemoved = true; |
1965 | 0 | } |
1966 | 0 | else |
1967 | 0 | { |
1968 | 0 | SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_COMMON, |
1969 | 0 | "> PKI remove: certificate thumbprint <%s> has not been found", pThumbprint); |
1970 | 0 | } |
1971 | 0 | } |
1972 | 0 | if (SOPC_STATUS_OK == status && bIsRemoved) |
1973 | 0 | { |
1974 | 0 | bool bAllCertIsRemoved = false; |
1975 | 0 | bool bAllRootIsRemoved = false; |
1976 | 0 | bool bAllCertIsCA = false; |
1977 | 0 | bool bAllRootIsCA = false; |
1978 | | /* Remove from all list */ |
1979 | 0 | if (NULL != pPKI->pAllCerts) |
1980 | 0 | { |
1981 | 0 | status = sopc_pki_remove_cert_by_thumbprint(&pPKI->pAllCerts, &pPKI->pAllCrl, pThumbprint, NULL, |
1982 | 0 | &bAllCertIsRemoved, &bAllCertIsCA); |
1983 | 0 | } |
1984 | 0 | if (NULL != pPKI->pAllRoots && SOPC_STATUS_OK == status) |
1985 | 0 | { |
1986 | 0 | status = sopc_pki_remove_cert_by_thumbprint(&pPKI->pAllRoots, &pPKI->pAllCrl, pThumbprint, NULL, |
1987 | 0 | &bAllRootIsRemoved, &bAllRootIsCA); |
1988 | 0 | SOPC_ASSERT(SOPC_STATUS_OK != status || bAllRootIsCA == bAllRootIsRemoved); |
1989 | 0 | } |
1990 | 0 | SOPC_ASSERT(SOPC_STATUS_OK != status || (bCertIsRemoved == bAllCertIsRemoved && bCertIsCA == bAllCertIsCA)); |
1991 | 0 | SOPC_ASSERT(SOPC_STATUS_OK != status || (bRootIsRemoved == bAllRootIsRemoved && bRootIsCA == bAllRootIsCA)); |
1992 | 0 | } |
1993 | | |
1994 | 0 | *pIsIssuer = bIsIssuer; |
1995 | 0 | *pIsRemoved = bIsRemoved; |
1996 | |
|
1997 | 0 | if (SOPC_STATUS_OK == status && bIsRemoved) |
1998 | 0 | { |
1999 | 0 | pPKI->pUpdateCb(pPKI->updateCbParam); |
2000 | 0 | } |
2001 | |
|
2002 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
2003 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
2004 | | |
2005 | 0 | return status; |
2006 | 0 | #endif |
2007 | 0 | } |
2008 | | |
2009 | | SOPC_ReturnStatus SOPC_PKIProvider_CreateFromStore(const char* directoryStorePath, SOPC_PKIProvider** ppPKI) |
2010 | 0 | { |
2011 | | #ifdef WITH_NO_CRYPTO |
2012 | | SOPC_UNUSED_ARG(ppPKI); |
2013 | | SOPC_UNUSED_ARG(directoryStorePath); |
2014 | | return SOPC_STATUS_NOT_SUPPORTED; |
2015 | | #else |
2016 | 0 | if (NULL == directoryStorePath || NULL == ppPKI) |
2017 | 0 | { |
2018 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
2019 | 0 | } |
2020 | | |
2021 | 0 | SOPC_ReturnStatus status = pki_create_from_store(directoryStorePath, false, ppPKI); |
2022 | 0 | return status; |
2023 | 0 | #endif |
2024 | 0 | } |
2025 | | |
2026 | | SOPC_ReturnStatus SOPC_PKIProvider_ValidateCertificate(SOPC_PKIProvider* pPKI, |
2027 | | const SOPC_CertificateList* pToValidate, |
2028 | | const SOPC_PKI_Profile* pProfile, |
2029 | | uint32_t* error) |
2030 | 0 | { |
2031 | | #ifdef WITH_NO_CRYPTO |
2032 | | SOPC_UNUSED_ARG(pPKI); |
2033 | | SOPC_UNUSED_ARG(pToValidate); |
2034 | | SOPC_UNUSED_ARG(pProfile); |
2035 | | SOPC_UNUSED_ARG(error); |
2036 | | return SOPC_STATUS_NOT_SUPPORTED; |
2037 | | #else |
2038 | 0 | if (NULL == pPKI) |
2039 | 0 | { |
2040 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
2041 | 0 | } |
2042 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Lock(&pPKI->mutex); |
2043 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
2044 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_INVALID_PARAMETERS; |
2045 | 0 | if (NULL != pPKI->pFnValidateCert) |
2046 | 0 | { |
2047 | 0 | status = pPKI->pFnValidateCert(pPKI, pToValidate, pProfile, error); |
2048 | 0 | } |
2049 | 0 | mutStatus = SOPC_Mutex_Unlock(&pPKI->mutex); |
2050 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
2051 | 0 | return status; |
2052 | 0 | #endif |
2053 | 0 | } |
2054 | | |
2055 | | SOPC_ReturnStatus SOPC_PKIProvider_CreateFromList(SOPC_CertificateList* pTrustedCerts, |
2056 | | SOPC_CRLList* pTrustedCrl, |
2057 | | SOPC_CertificateList* pIssuerCerts, |
2058 | | SOPC_CRLList* pIssuerCrl, |
2059 | | SOPC_PKIProvider** ppPKI) |
2060 | 0 | { |
2061 | | #ifdef WITH_NO_CRYPTO |
2062 | | SOPC_UNUSED_ARG(pTrustedCerts); |
2063 | | SOPC_UNUSED_ARG(pTrustedCrl); |
2064 | | SOPC_UNUSED_ARG(pIssuerCerts); |
2065 | | SOPC_UNUSED_ARG(pIssuerCrl); |
2066 | | SOPC_UNUSED_ARG(ppPKI); |
2067 | | return SOPC_STATUS_NOT_SUPPORTED; |
2068 | | #else |
2069 | 0 | SOPC_ReturnStatus status = SOPC_STATUS_OK; |
2070 | 0 | SOPC_PKIProvider* pPKI = NULL; |
2071 | 0 | SOPC_CertificateList* tmp_pTrustedRoots = NULL; /* trusted root CA */ |
2072 | 0 | SOPC_CertificateList* tmp_pIssuerRoots = NULL; /* issuer root CA */ |
2073 | 0 | SOPC_CertificateList* tmp_pAllRoots = NULL; /* issuer + trusted roots */ |
2074 | 0 | SOPC_CertificateList* tmp_pAllCerts = NULL; /* issuer + trusted certs */ |
2075 | 0 | SOPC_CertificateList* tmp_pAllTrusted = NULL; /* trusted CAs and certs */ |
2076 | |
|
2077 | 0 | SOPC_CRLList* tmp_pAllCrl = NULL; /* issuer crl + trusted crl */ |
2078 | |
|
2079 | 0 | SOPC_CertificateList* tmp_pTrustedCerts = NULL; /* trusted intermediate CA + trusted certificates */ |
2080 | 0 | SOPC_CRLList* tmp_pTrustedCrl = NULL; /* CRLs of trusted intermediate CA and trusted root CA */ |
2081 | 0 | SOPC_CertificateList* tmp_pIssuerCerts = NULL; /* issuer intermediate CA + issuer root CA */ |
2082 | 0 | SOPC_CRLList* tmp_pIssuerCrl = NULL; /* CRLs of issuer intermediate CA and issuer root CA */ |
2083 | 0 | bool bTrustedCaFound = false; |
2084 | 0 | bool bIssuerCaFound = false; |
2085 | 0 | uint32_t listLength = 0; |
2086 | |
|
2087 | 0 | if (NULL == ppPKI) |
2088 | 0 | { |
2089 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
2090 | 0 | } |
2091 | | |
2092 | | /* Check the number of certificates plus CRLs of the PKI */ |
2093 | 0 | status = sopc_pki_get_list_length(pTrustedCerts, pTrustedCrl, pIssuerCerts, pIssuerCrl, &listLength); |
2094 | 0 | if (SOPC_STATUS_OK != status) |
2095 | 0 | { |
2096 | 0 | return status; |
2097 | 0 | } |
2098 | 0 | if (SOPC_PKI_MAX_NB_CERT_AND_CRL < listLength) |
2099 | 0 | { |
2100 | 0 | SOPC_Logger_TraceError(SOPC_LOG_MODULE_COMMON, |
2101 | 0 | "> PKI creation error: too many (%" PRIu32 |
2102 | 0 | ") certificates and CRLs. The maximum configured is %" PRIu32 |
2103 | 0 | ", please change SOPC_PKI_MAX_NB_CERT_AND_CRL", |
2104 | 0 | listLength, (uint32_t) SOPC_PKI_MAX_NB_CERT_AND_CRL); |
2105 | 0 | return SOPC_STATUS_INVALID_PARAMETERS; |
2106 | 0 | } |
2107 | | |
2108 | | /* |
2109 | | - Check that pTrustedCerts is not empty. |
2110 | | - Check if there are CAs but no CRLs. |
2111 | | - Check if issuerCerts list is only filled with CA. |
2112 | | - Check and warn if issuerCerts is not empty but pTrustedCerts is only filed with CA. |
2113 | | In this case, if there is no root into pTrustedCerts then |
2114 | | no certificates will be accepted during validation process. |
2115 | | - Check and warn in case no root defined but trusted certificates defined. |
2116 | | In this case, only trusted self-signed issued certificates will be accepted. |
2117 | | */ |
2118 | 0 | if (SOPC_STATUS_OK == status) |
2119 | 0 | { |
2120 | 0 | status = sopc_pki_check_lists(pTrustedCerts, pIssuerCerts, pTrustedCrl, pIssuerCrl, &bTrustedCaFound, |
2121 | 0 | &bIssuerCaFound); |
2122 | 0 | if (SOPC_STATUS_OK != status) |
2123 | 0 | { |
2124 | 0 | return status; |
2125 | 0 | } |
2126 | 0 | } |
2127 | | |
2128 | | /* Copy the lists */ |
2129 | 0 | status = SOPC_KeyManager_Certificate_Copy(pTrustedCerts, &tmp_pTrustedCerts); |
2130 | 0 | if (SOPC_STATUS_OK == status && NULL != pTrustedCrl) |
2131 | 0 | { |
2132 | 0 | status = SOPC_KeyManager_CRL_Copy(pTrustedCrl, &tmp_pTrustedCrl); |
2133 | 0 | } |
2134 | 0 | if (SOPC_STATUS_OK == status && NULL != pIssuerCerts) |
2135 | 0 | { |
2136 | 0 | status = SOPC_KeyManager_Certificate_Copy(pIssuerCerts, &tmp_pIssuerCerts); |
2137 | 0 | } |
2138 | 0 | if (SOPC_STATUS_OK == status && NULL != pIssuerCrl) |
2139 | 0 | { |
2140 | 0 | status = SOPC_KeyManager_CRL_Copy(pIssuerCrl, &tmp_pIssuerCrl); |
2141 | 0 | } |
2142 | | |
2143 | | /* Check the CRL-CA association before creating the PKI. */ |
2144 | 0 | bool bTrustedCRL = false; |
2145 | 0 | bool bIssuerCRL = false; |
2146 | 0 | if (SOPC_STATUS_OK == status) |
2147 | 0 | { |
2148 | 0 | if (bTrustedCaFound && NULL != tmp_pTrustedCrl) |
2149 | 0 | { |
2150 | 0 | status = SOPC_KeyManager_CertificateList_CheckCRL(tmp_pTrustedCerts, tmp_pTrustedCrl, &bTrustedCRL); |
2151 | 0 | } |
2152 | 0 | else |
2153 | 0 | { |
2154 | 0 | bTrustedCRL = true; |
2155 | 0 | } |
2156 | 0 | } |
2157 | 0 | if (SOPC_STATUS_OK == status) |
2158 | 0 | { |
2159 | 0 | if (bIssuerCaFound && NULL != tmp_pIssuerCrl) |
2160 | 0 | { |
2161 | 0 | status = SOPC_KeyManager_CertificateList_CheckCRL(tmp_pIssuerCerts, tmp_pIssuerCrl, &bIssuerCRL); |
2162 | 0 | } |
2163 | 0 | else |
2164 | 0 | { |
2165 | 0 | bIssuerCRL = true; |
2166 | 0 | } |
2167 | 0 | } |
2168 | 0 | if (SOPC_STATUS_OK == status && (!bTrustedCRL || !bIssuerCRL)) |
2169 | 0 | { |
2170 | 0 | if (!bTrustedCRL) |
2171 | 0 | { |
2172 | 0 | SOPC_Logger_TraceWarning( |
2173 | 0 | SOPC_LOG_MODULE_COMMON, |
2174 | 0 | "> PKI creation warning: Not all certificate authorities in given trusted certificates have at least " |
2175 | 0 | "one certificate revocation list! Certificates issued by these CAs will be refused."); |
2176 | 0 | } |
2177 | 0 | if (!bIssuerCRL) |
2178 | 0 | { |
2179 | 0 | SOPC_Logger_TraceWarning( |
2180 | 0 | SOPC_LOG_MODULE_COMMON, |
2181 | 0 | "> PKI creation warning: Not all certificate authorities in given issuer certificates have at least " |
2182 | 0 | "one certificate revocation list! Certificates issued by these CAs will be refused."); |
2183 | 0 | } |
2184 | 0 | } |
2185 | | /* Retrieve the root from list */ |
2186 | 0 | if (SOPC_STATUS_OK == status) |
2187 | 0 | { |
2188 | 0 | status = SOPC_PKIProviderInternal_SplitRootFromCertList(&tmp_pTrustedCerts, &tmp_pTrustedRoots); |
2189 | 0 | } |
2190 | 0 | if (SOPC_STATUS_OK == status && NULL != tmp_pIssuerCerts) |
2191 | 0 | { |
2192 | 0 | status = SOPC_PKIProviderInternal_SplitRootFromCertList(&tmp_pIssuerCerts, &tmp_pIssuerRoots); |
2193 | 0 | } |
2194 | | /* Merge trusted and issuer list */ |
2195 | 0 | if (SOPC_STATUS_OK == status) |
2196 | 0 | { |
2197 | 0 | status = sopc_pki_merge_certificates(tmp_pIssuerCerts, tmp_pTrustedCerts, &tmp_pAllCerts); |
2198 | 0 | } |
2199 | 0 | if (SOPC_STATUS_OK == status) |
2200 | 0 | { |
2201 | 0 | status = sopc_pki_merge_certificates(tmp_pIssuerRoots, tmp_pTrustedRoots, &tmp_pAllRoots); |
2202 | 0 | } |
2203 | 0 | if (SOPC_STATUS_OK == status) |
2204 | 0 | { |
2205 | 0 | status = sopc_pki_merge_crls(tmp_pIssuerCrl, tmp_pTrustedCrl, &tmp_pAllCrl); |
2206 | 0 | } |
2207 | 0 | if (SOPC_STATUS_OK == status) |
2208 | 0 | { |
2209 | 0 | status = SOPC_KeyManager_Certificate_Copy(pTrustedCerts, &tmp_pAllTrusted); |
2210 | 0 | } |
2211 | | /* Create the PKI */ |
2212 | 0 | if (SOPC_STATUS_OK == status) |
2213 | 0 | { |
2214 | 0 | pPKI = SOPC_Calloc(1, sizeof(SOPC_PKIProvider)); |
2215 | 0 | if (NULL == pPKI) |
2216 | 0 | { |
2217 | 0 | status = SOPC_STATUS_OUT_OF_MEMORY; |
2218 | 0 | } |
2219 | 0 | } |
2220 | |
|
2221 | 0 | if (SOPC_STATUS_OK == status) |
2222 | 0 | { |
2223 | 0 | SOPC_ReturnStatus mutStatus = SOPC_Mutex_Initialization(&pPKI->mutex); |
2224 | 0 | SOPC_ASSERT(SOPC_STATUS_OK == mutStatus); |
2225 | 0 | pPKI->pTrustedRoots = tmp_pTrustedRoots; |
2226 | 0 | pPKI->pTrustedCerts = tmp_pTrustedCerts; |
2227 | 0 | pPKI->pTrustedCrl = tmp_pTrustedCrl; |
2228 | 0 | pPKI->pIssuerRoots = tmp_pIssuerRoots; |
2229 | 0 | pPKI->pIssuerCerts = tmp_pIssuerCerts; |
2230 | 0 | pPKI->pIssuerCrl = tmp_pIssuerCrl; |
2231 | 0 | pPKI->pAllCerts = tmp_pAllCerts; |
2232 | 0 | pPKI->pAllRoots = tmp_pAllRoots; |
2233 | 0 | pPKI->pAllTrusted = tmp_pAllTrusted; |
2234 | 0 | pPKI->pAllCrl = tmp_pAllCrl; |
2235 | 0 | pPKI->pRejectedList = NULL; |
2236 | 0 | pPKI->directoryStorePath = NULL; |
2237 | 0 | pPKI->pFnValidateCert = &SOPC_PKIProviderInternal_ValidateProfileAndCertificate; |
2238 | 0 | pPKI->pUpdateCb = NULL; |
2239 | 0 | pPKI->updateCbParam = 0; |
2240 | 0 | pPKI->isPermissive = false; |
2241 | 0 | *ppPKI = pPKI; |
2242 | 0 | } |
2243 | 0 | else |
2244 | 0 | { |
2245 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pTrustedRoots); |
2246 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pIssuerRoots); |
2247 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pAllRoots); |
2248 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pAllTrusted); |
2249 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pTrustedCerts); |
2250 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pIssuerCerts); |
2251 | 0 | SOPC_KeyManager_Certificate_Free(tmp_pAllCerts); |
2252 | 0 | SOPC_KeyManager_CRL_Free(tmp_pTrustedCrl); |
2253 | 0 | SOPC_KeyManager_CRL_Free(tmp_pIssuerCrl); |
2254 | 0 | SOPC_KeyManager_CRL_Free(tmp_pAllCrl); |
2255 | 0 | } |
2256 | | |
2257 | 0 | return status; |
2258 | 0 | #endif |
2259 | 0 | } |