Application configuration: use of PEM certificate file leads to configuration or connection failure
Description
When a server is configured with certificate in PEM format, client connection attempts fail and only the following elements are visible in the server logs:
[2022/05/13 14:29:59.949] ClientSer (Debug) SocketEvent: INT_SOCKET_LISTENER_CONNECTION_ATTEMPT socketIdx=1
[2022/05/13 14:29:59.949] ClientSer (Debug) ScListenerMgr: SOCKET_LISTENER_CONNECTION epCfgIdx=1 socketIdx=2
[2022/05/13 14:29:59.949] ClientSer (Debug) ScStateMgr: INT_EP_SC_CREATE epCfgIdx=1 socketIdx=2
[2022/05/13 14:29:59.949] ClientSer (Debug) SocketEvent: SOCKET_CLOSE socketIdx=2 connectionIdx=0
[2022/05/13 14:29:59.949] ClientSer (Warning) ScStateMgr: INT_EP_SC_CREATE failed (no more SCs available) epCfgIdx=1 socketIdx=2
It seems the INT_EP_SC_CREATE failure is misinterpreted since the issue is not related to the number of SCs available.
The following error is also display but on std or err output which is not sufficient:
> KeyManager: certificate buffer parse failed with error code: -0x2180
The callstack is the following:
#0 0x00007f6a7b2077a0 in mbedtls_x509_crt_parse () from /users/vincent/git/INGOPCS/build/lib/libs2opc_common.so
#1 0x00007f6a7b1e3dc2 in SOPC_KeyManager_Certificate_CreateOrAddFromDER (
bufferDER=0xfb5730 "Certificate:\n Data:\n Version: 1 (0x0)\n Serial Number:\n", ' ' <repeats 12 times>, "45:ce:e9:25:1e:fb:a6:a7:19:ec:ac:b0:5a:5e:8f:9a:ff:37:07:29\n Signature Algorithm: sha256WithRSAEncryption\n "..., lenDER=3828, ppCert=0x7f6a7b2ec340 <secureConnectionsArray+608>) at /users/vincent/git/INGOPCS/src/Common/crypto/mbedtls/key_manager_lib.c:270
#2 0x00007f6a7b28f596 in sc_init_key_and_certs (sc=0x7f6a7b2ec218 <secureConnectionsArray+312>) at /users/vincent/git/INGOPCS/src/ClientServer/secure_channels/sopc_secure_connection_state_mgr.c:2399
#3 0x00007f6a7b28f6dd in initServerSC (socketIndex=2, serverEndpointConfigIdx=1, conn_idx=0x7f6a78cfbe44) at /users/vincent/git/INGOPCS/src/ClientServer/secure_channels/sopc_secure_connection_state_mgr.c:2439
#4 0x00007f6a7b28fc94 in SOPC_SecureConnectionStateMgr_OnInternalEvent (event=INT_EP_SC_CREATE, eltId=1, params=0, auxParam=2)
at /users/vincent/git/INGOPCS/src/ClientServer/secure_channels/sopc_secure_connection_state_mgr.c:2631
#5 0x00007f6a7b28a120 in SOPC_SecureChannels_OnInternalEvent (handler=0xfad4d0, event=1024, eltId=1, params=0, auxParam=2)
Analysis
Even if SOPC_KeyManager_Certificate_CreateOrAddFromDER
does not indicate it accepts PEM format mbedtls_x509_crt_parse
does therefore it does not explain what is going on and should be investigated.
First analysis shows that PEM format can be parsed except the '\0' should be considered when providing buffer length which is working with the following modification:
diff --git a/src/Common/crypto/mbedtls/key_manager_lib.c b/src/Common/crypto/mbedtls/key_manager_lib.c
index 92f25e0f8..12f7cda56 100644
--- a/src/Common/crypto/mbedtls/key_manager_lib.c
+++ b/src/Common/crypto/mbedtls/key_manager_lib.c
@@ -267,7 +267,7 @@ SOPC_ReturnStatus SOPC_KeyManager_Certificate_CreateOrAddFromDER(const uint8_t*
if (SOPC_STATUS_OK == status)
{
- int err = mbedtls_x509_crt_parse(&pCert->crt, bufferDER, lenDER);
+ int err = mbedtls_x509_crt_parse(&pCert->crt, bufferDER, lenDER+1);
if (0 != err)
{
status = SOPC_STATUS_NOK;
There are still remaining issues for PEM format once the patch is applied.
Indeed the SOPC_Server_Config.serverCertificate
and SOPC_SecureChannel_Config.crt_srv
fields contain the file content as a buffer, which means PEM or DER format. But Get_Endpoints
services and CreateSession
services use those fields as if it already was in DER format.
The SOPC_SerializedCertificate
of a certificate shall always been built by decoding certificate from DER or PEM format and then by encoding it again. Note that it will be an issue for certificate chain that is not supported in DER format (see last section of this issue)
The following patches are fixing the server-side issues by decoding/encoding to DER file loading:
diff --git a/src/Common/crypto/sopc_key_manager.c b/src/Common/crypto/sopc_key_manager.c
index 3f33ddada..b0bee7578 100644
--- a/src/Common/crypto/sopc_key_manager.c
+++ b/src/Common/crypto/sopc_key_manager.c
@@ -117,7 +117,26 @@ SOPC_ReturnStatus SOPC_KeyManager_SerializedCertificate_CreateFromDER(const uint
SOPC_ReturnStatus SOPC_KeyManager_SerializedCertificate_CreateFromFile(const char* path,
SOPC_SerializedCertificate** cert)
{
- return SOPC_Buffer_ReadFile(path, cert);
+ SOPC_Buffer* tmpBuffer = NULL;
+ SOPC_ReturnStatus status = SOPC_Buffer_ReadFile(path, &tmpBuffer);
+ SOPC_CertificateList* certList = NULL;
+
+ if (SOPC_STATUS_OK == status)
+ {
+ status = SOPC_KeyManager_Certificate_CreateOrAddFromDER(tmpBuffer->data, tmpBuffer->length, &certList);
+ }
+ if (SOPC_STATUS_OK == status)
+ {
+ SOPC_Buffer_Clear(tmpBuffer);
+ status = SOPC_KeyManager_Certificate_ToDER(certList, &tmpBuffer->data, &tmpBuffer->length);
+ }
+ if (SOPC_STATUS_OK == status)
+ {
+ *cert = tmpBuffer;
+ tmpBuffer = NULL;
+ }
+ SOPC_Buffer_Delete(tmpBuffer);
+ return status;
}
Regarding the PEM file format containing a chain of certificates, the OPN will fail due to the following check that it is not a chain:
SOPC_ReturnStatus SOPC_KeyManager_Certificate_ToDER(const SOPC_CertificateList* pCert,
uint8_t** ppDest,
uint32_t* pLenAllocated)
SOPC_ReturnStatus status = certificate_check_single(pCert);
To be analysed / treated
Implement final fixes based on analysis result.
Moreover mbedtls_x509_crt_parse
ignores chain certificate when provided in DER format (keep the first only ?). It is an issue if we want to configure a server certificate with its chain and moreover this function is certainly used when receiving a certificate chain through OPC UA service (OPN, GetEndpoints, etc.).
Finally the log shall indicate an error in case of certificate parse failure and the warning message seems incorrect.