From 676f465b485b254d1611c1780c2a4a6d6f143797 Mon Sep 17 00:00:00 2001 From: Julius Pfrommer Date: Tue, 28 Nov 2023 22:47:26 +0100 Subject: [PATCH 1/2] fix(server): Use only the leaf certificate from the asymmetric security header The fix was provided by Phuong Nguyen of Hilscher in #6083. --- src/server/ua_services_securechannel.c | 38 +++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/server/ua_services_securechannel.c b/src/server/ua_services_securechannel.c index 3f9b0f304f7..22cbaf8da29 100644 --- a/src/server/ua_services_securechannel.c +++ b/src/server/ua_services_securechannel.c @@ -7,6 +7,7 @@ * Copyright 2015 (c) Oleksiy Vasylyev * Copyright 2017 (c) Stefan Profanter, fortiss GmbH * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB + * Copyright 2023 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Phuong Nguyen) */ #include "ua_server_internal.h" @@ -183,6 +184,34 @@ UA_Server_createSecureChannel(UA_Server *server, UA_Connection *connection) { return UA_STATUSCODE_GOOD; } +/* Get pointer to leaf certificate of a specified valid chain of DER encoded + * certificates */ +static void +getLeafCertificate(const UA_ByteString *chain, UA_ByteString *leaf) { + /* Detect DER encoded X.509 v3 certificate. If the DER detection fails, + * return the entire chain. + * + * The OPC UA standard requires this to be DER. But we also allow other + * formats like PEM. Afterwards it depends on the crypto backend to parse + * it. mbedTLS and OpenSSL detect the format automatically. */ + if(chain->length < 4 || chain->data[0] != 0x30 || chain->data[1] != 0x82) { + *leaf = *chain; + return; + } + + /* The certificate length is encoded in the next 2 bytes. */ + size_t leafLen = 4; /* Magic numbers + length bytes */ + leafLen += (size_t)(((uint16_t)chain->data[2]) << 8); + leafLen += chain->data[3]; + + /* Length consistency check */ + if(leafLen > chain->length) + return; + + leaf->data = chain->data; + leaf->length = leafLen; +} + UA_StatusCode UA_Server_configSecureChannel(void *application, UA_SecureChannel *channel, const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) { @@ -209,11 +238,18 @@ UA_Server_configSecureChannel(void *application, UA_SecureChannel *channel, if(!securityPolicy) return UA_STATUSCODE_BADSECURITYPOLICYREJECTED; + /* If the sender provides a chain of certificates then we shall extract the + * ApplicationInstanceCertificate. and ignore the extra bytes. See also: OPC + * UA Part 6, V1.04, 6.7.2.3 Security Header, Table 42 - Asymmetric + * algorithm Security header */ + UA_ByteString appInstanceCertificate = UA_BYTESTRING_NULL; + getLeafCertificate(&asymHeader->senderCertificate, &appInstanceCertificate); + /* Create the channel context and parse the sender (remote) certificate used for the * secureChannel. */ UA_StatusCode retval = UA_SecureChannel_setSecurityPolicy(channel, securityPolicy, - &asymHeader->senderCertificate); + &appInstanceCertificate); if(retval != UA_STATUSCODE_GOOD) return retval; From 70ff3501ddecd7e7594ebc63e2365994d59e010d Mon Sep 17 00:00:00 2001 From: Julius Pfrommer Date: Wed, 29 Nov 2023 07:23:24 +0100 Subject: [PATCH 2/2] refactor(build): Bump version to v1.3.9 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5300b12f6e6..7a051f12f6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # overwritten with more detailed information if git is available. set(OPEN62541_VER_MAJOR 1) set(OPEN62541_VER_MINOR 3) -set(OPEN62541_VER_PATCH 8) +set(OPEN62541_VER_PATCH 9) set(OPEN62541_VER_LABEL "-undefined") # like "-rc1" or "-g4538abcd" or "-g4538abcd-dirty" set(OPEN62541_VER_COMMIT "unknown-commit")