diff --git a/.azure-pipelines/azure-pipelines-dist.yml b/.azure-pipelines/azure-pipelines-dist.yml index de12655b011..9b07fb6b54c 100644 --- a/.azure-pipelines/azure-pipelines-dist.yml +++ b/.azure-pipelines/azure-pipelines-dist.yml @@ -5,7 +5,7 @@ jobs: - job: 'dist_debian' displayName: 'Dist (debian)' pool: - vmImage: 'ubuntu-18.04' + vmImage: 'ubuntu-20.04' steps: - checkout: self submodules: recursive diff --git a/.azure-pipelines/azure-pipelines-linux.yml b/.azure-pipelines/azure-pipelines-linux.yml index 4240cfcae6d..6625754ea2f 100644 --- a/.azure-pipelines/azure-pipelines-linux.yml +++ b/.azure-pipelines/azure-pipelines-linux.yml @@ -5,7 +5,7 @@ jobs: - job: 'cross_freeRTOS' displayName: 'Arch (freeRTOS)' pool: - vmImage: 'ubuntu-18.04' + vmImage: 'ubuntu-20.04' variables: IDF_PATH: $(Build.BinariesDirectory)/esp-idf steps: diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 50201b43225..132149ec9fe 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -9,7 +9,6 @@ jobs: matrix: include: - build_name: "Debug Build & Unit Tests (gcc)" - cmd_deps: sudo apt-get install -y -qq mosquitto cmd_action: unit_tests - build_name: "Debug Build & Unit Tests without Subscriptions (gcc)" cmd_deps: "" @@ -24,10 +23,10 @@ jobs: cmd_deps: "" cmd_action: unit_tests_alarms - build_name: "Debug Build & Unit Tests (clang)" - cmd_deps: sudo apt-get install -y -qq clang-11 clang-tools-11 mosquitto + cmd_deps: sudo apt-get install -y -qq clang-11 clang-tools-11 cmd_action: CC=clang-11 CXX=clang++-11 unit_tests - build_name: "Debug Build & Unit Tests (tcc)" - cmd_deps: sudo apt-get install -y -qq tcc mosquitto + cmd_deps: sudo apt-get install -y -qq tcc cmd_action: CC=tcc unit_tests - build_name: "Encryption (MbedTLS) Build & Unit Tests (gcc)" cmd_deps: sudo apt-get install -y -qq libmbedtls-dev @@ -41,9 +40,9 @@ jobs: - build_name: "Encryption (LibreSSL) Build & Unit Tests (gcc)" cmd_deps: | sudo apt-get install -y -qq curl - curl https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.4.2.tar.gz --output libressl.tar.gz + curl https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-3.7.2.tar.gz --output libressl.tar.gz tar -xvz -f libressl.tar.gz - cd libressl-3.4.2 + cd libressl-3.7.2 ./configure sudo make install cmd_action: unit_tests_encryption LIBRESSL @@ -98,17 +97,36 @@ jobs: cmd_deps: sudo apt-get install -y -qq clang-11 clang-tools-11 libmbedtls-dev cmd_action: build_clang_analyzer name: ${{matrix.build_name}} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest + container: + image: ghcr.io/marwinglaser/ci:ubuntu-20.04 + options: --privileged + services: + mosquitto: + image: eclipse-mosquitto:1.6-openssl + env: + OPEN62541_TEST_MQTT_BROKER: opc.mqtt://mosquitto:1883 steps: - - uses: actions/checkout@v2 + - name: Work around disabled ipv6 on actions container networks + run: | + IPV6="$(cat /proc/sys/net/ipv6/conf/eth0/disable_ipv6)" + echo "Current IPv6 status on eth0: $IPV6" + [ "$IPV6" = "1" ] || exit + + echo 0 | sudo tee /proc/sys/net/ipv6/conf/eth0/disable_ipv6 > /dev/null + IPV6="$(cat /proc/sys/net/ipv6/conf/eth0/disable_ipv6)" + echo "New IPv6 status on eth0: $IPV6" + [ "$IPV6" = "0" ] || { echo "Failed to enable IPv6 on eth0"; exit 1; } + - uses: actions/checkout@v4 with: submodules: true - name: Install Dependencies run: | sudo apt-get update - sudo apt-get install -y -qq python3-sphinx graphviz check + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq cmake libcap2-bin pkg-config libssl-dev python3-sphinx graphviz check ${{ matrix.cmd_deps }} - name: ${{matrix.build_name}} + shell: bash run: source tools/ci.sh && ${{matrix.cmd_action}} env: ETHERNET_INTERFACE: eth0 diff --git a/.github/workflows/build_ubuntu2204.yml b/.github/workflows/build_ubuntu2204.yml index 216c0665c08..77e4dfeadea 100644 --- a/.github/workflows/build_ubuntu2204.yml +++ b/.github/workflows/build_ubuntu2204.yml @@ -12,17 +12,31 @@ jobs: cmd_deps: sudo apt-get install -y -qq openssl cmd_action: unit_tests_encryption OPENSSL name: ${{matrix.build_name}} - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest + container: + image: ghcr.io/marwinglaser/ci:ubuntu-22.04 + options: --privileged steps: - - uses: actions/checkout@v2 + - name: Work around disabled ipv6 on actions container networks + run: | + IPV6="$(cat /proc/sys/net/ipv6/conf/eth0/disable_ipv6)" + echo "Current IPv6 status on eth0: $IPV6" + [ "$IPV6" = "1" ] || exit + + echo 0 | sudo tee /proc/sys/net/ipv6/conf/eth0/disable_ipv6 > /dev/null + IPV6="$(cat /proc/sys/net/ipv6/conf/eth0/disable_ipv6)" + echo "New IPv6 status on eth0: $IPV6" + [ "$IPV6" = "0" ] || { echo "Failed to enable IPv6 on eth0"; exit 1; } + - uses: actions/checkout@v4 with: submodules: true - name: Install Dependencies run: | sudo apt-get update - sudo apt-get install -y -qq python3-sphinx graphviz check + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq cmake pkg-config libssl-dev python3-sphinx graphviz check ${{ matrix.cmd_deps }} - name: ${{matrix.build_name}} + shell: bash run: source tools/ci.sh && ${{matrix.cmd_action}} env: ETHERNET_INTERFACE: eth0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c26c72a5c2..29d432bb856 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 9) +set(OPEN62541_VER_PATCH 19) set(OPEN62541_VER_LABEL "-undefined") # like "-rc1" or "-g4538abcd" or "-g4538abcd-dirty" set(OPEN62541_VER_COMMIT "unknown-commit") @@ -605,8 +605,12 @@ if(UA_ENABLE_ENCRYPTION_OPENSSL OR UA_ENABLE_MQTT_TLS_OPENSSL) # use the OpenSSL encryption library # https://cmake.org/cmake/help/v3.0/module/FindOpenSSL.html find_package(OpenSSL REQUIRED) - list(APPEND open62541_LIBRARIES ${OPENSSL_LIBRARIES}) - endif () + list(APPEND open62541_LIBRARIES "${OPENSSL_LIBRARIES}") + if(WIN32) + # Add bestcrypt for windows systems + list(APPEND open62541_LIBRARIES bcrypt) + endif() +endif() if(UA_ENABLE_ENCRYPTION_LIBRESSL) # See https://github.com/libressl-portable/portable/blob/master/FindLibreSSL.cmake @@ -624,6 +628,10 @@ if(UA_ENABLE_ENCRYPTION_MBEDTLS OR UA_ENABLE_PUBSUB_ENCRYPTION) # defined in /tools/cmake/FindMbedTLS.cmake. find_package(MbedTLS REQUIRED) list(APPEND open62541_LIBRARIES ${MBEDTLS_LIBRARIES}) + if(WIN32) + # Add bestcrypt for windows systems + list(APPEND open62541_LIBRARIES bcrypt) + endif() endif() if(UA_ENABLE_TPM2_SECURITY) @@ -695,6 +703,12 @@ if(NOT UA_FORCE_CPP AND (CMAKE_COMPILER_IS_GNUCC OR "x${CMAKE_C_COMPILER_ID}" ST # Use a strict subset of the C and C++ languages check_add_cc_flag("-Wc++-compat") + # Wc++-compat enables additional goto/jump restrictions. + # But modern compilers do a detailed analysis of values + # are actually used uninitialized after a jump: + # TODO: The following flag should not be required + check_add_cc_flag("-Wno-jump-misses-init") + # Check that format strings (printf/scanf) are sane check_add_cc_flag("-Wformat") check_add_cc_flag("-Wformat-security") diff --git a/deps/base64.c b/deps/base64.c index ce60b663e1c..2b5d6b70870 100644 --- a/deps/base64.c +++ b/deps/base64.c @@ -1,10 +1,9 @@ /* - * Base64 encoding: Copyright (c) 2005-2011, Jouni Malinen - * This software may be distributed under the terms of the BSD license. + * Base64 encoding/decoding (RFC1341) + * Copyright (c) 2005-2011, Jouni Malinen * - * Base64 decoding: Copyright (c) 2016, polfosol - * Posted at https://stackoverflow.com/a/37109258 under the CC-BY-SA Creative - * Commons license. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "base64.h" @@ -55,61 +54,79 @@ UA_base64(const unsigned char *src, size_t len, size_t *out_len) { return out; } -static const uint32_t from_b64[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, - 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; +static unsigned char dtable[256] = { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 62 , 0x80, 62 , 0x80, 63 , + 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 0x80, 0x80, 0x80, 0, 0x80, 0x80, + 0x80, 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , + 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 0x80, 0x80, 0x80, 0x80, 63 , + 0x80, 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , + 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 51 , 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 +}; unsigned char * UA_unbase64(const unsigned char *src, size_t len, size_t *out_len) { - // we need a minimum length - if(len <= 2) { + /* Empty base64 results in an empty byte-string */ + if(len == 0) { *out_len = 0; return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL; } - const unsigned char *p = src; - size_t pad1 = len % 4 || p[len - 1] == '='; - size_t pad2 = pad1 && (len % 4 > 2 || p[len - 2] != '='); - const size_t last = (len - pad1) / 4 << 2; - - unsigned char *str = (unsigned char*)UA_malloc(last / 4 * 3 + pad1 + pad2); - if(!str) - return NULL; - - unsigned char *pos = str; - for(size_t i = 0; i < last; i += 4) { - uint32_t n = from_b64[p[i]] << 18 | from_b64[p[i + 1]] << 12 | - from_b64[p[i + 2]] << 6 | from_b64[p[i + 3]]; - *pos++ = (unsigned char)(n >> 16); - *pos++ = (unsigned char)(n >> 8 & 0xFF); - *pos++ = (unsigned char)(n & 0xFF); - } + /* The input length must be a multiple of four */ + if(len % 4 != 0) + return NULL; + + /* Allocate the output string */ + size_t olen = len / 4 * 3; + unsigned char *out = (unsigned char*)UA_malloc(olen); + if(!out) + return NULL; - if(pad1) { - if (last + 1 >= len) { - UA_free(str); - *out_len = 0; - return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL; - } - uint32_t n = from_b64[p[last]] << 18 | from_b64[p[last + 1]] << 12; - *pos++ = (unsigned char)(n >> 16); - if(pad2) { - if (last + 2 >= len) { - UA_free(str); - *out_len = 0; - return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL; + /* Iterate over the input */ + size_t pad = 0; + unsigned char count = 0; + unsigned char block[4]; + unsigned char *pos = out; + for(size_t i = 0; i < len; i++) { + unsigned char tmp = dtable[src[i]]; + if(tmp == 0x80) + goto error; /* Invalid input */ + + if(src[i] == '=') + pad++; + + block[count] = tmp; + count++; + if(count == 4) { + *pos++ = (unsigned char)((block[0] << 2) | (block[1] >> 4)); + *pos++ = (unsigned char)((block[1] << 4) | (block[2] >> 2)); + *pos++ = (unsigned char)((block[2] << 6) | block[3]); + if(pad) { + if(pad == 1) + pos--; + else if(pad == 2) + pos -= 2; + else + goto error; /* Invalid padding */ + break; } - n |= from_b64[p[last + 2]] << 6; - *pos++ = (unsigned char)(n >> 8 & 0xFF); - } - } + count = 0; + } + } + + *out_len = (size_t)(pos - out); + return out; - *out_len = (uintptr_t)(pos - str); - return str; + error: + UA_free(out); + return NULL; } diff --git a/deps/mdnsd b/deps/mdnsd index 3151afe5899..488d24fb9d4 160000 --- a/deps/mdnsd +++ b/deps/mdnsd @@ -1 +1 @@ -Subproject commit 3151afe5899dba5125dffa9f4cf3ae1fe2edc0f0 +Subproject commit 488d24fb9d427aec77df180268f0291eeee7fb8b diff --git a/examples/discovery/server_multicast.c b/examples/discovery/server_multicast.c index 861e29e01a2..a31777b041f 100644 --- a/examples/discovery/server_multicast.c +++ b/examples/discovery/server_multicast.c @@ -241,7 +241,7 @@ int main(int argc, char **argv) { config->mdnsConfig.mdnsServerName = UA_String_fromChars("Sample Multicast Server"); //setting custom outbound interface - config->mdnsInterfaceIP = UA_String_fromChars("42.42.42.42"); //this line will produce an error and set the interface to 0.0.0.0 + config->mdnsInterfaceIP = UA_String_fromChars("0.0.0.0"); // See http://www.opcfoundation.org/UA/schemas/1.03/ServerCapabilities.csv // For a LDS server, you should only indicate the LDS capability. diff --git a/include/open62541/architecture_definitions.h b/include/open62541/architecture_definitions.h index 0bbde78b795..c7e9e10e98b 100644 --- a/include/open62541/architecture_definitions.h +++ b/include/open62541/architecture_definitions.h @@ -356,10 +356,11 @@ UA_STATIC_ASSERT(sizeof(bool) == 1, cannot_overlay_integers_with_large_bool); * Float Endianness * ^^^^^^^^^^^^^^^^ * The definition ``UA_FLOAT_IEEE754`` is set to true when the floating point - * number representation of the target architecture is IEEE 754. The definition - * ``UA_FLOAT_LITTLE_ENDIAN`` is set to true when the floating point number - * representation is in little-endian encoding. */ - + * number representation of the target architecture is IEEE 754. This can be + * set from outside with ``-DUA_FLOAT_IEEE754=1``. + * The definition ``UA_FLOAT_LITTLE_ENDIAN`` is set to true when the floating + * point number representation is in little-endian encoding. */ +#ifndef UA_FLOAT_IEEE754 #if defined(_WIN32) # define UA_FLOAT_IEEE754 1 #elif defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || \ @@ -368,9 +369,12 @@ UA_STATIC_ASSERT(sizeof(bool) == 1, cannot_overlay_integers_with_large_bool); # define UA_FLOAT_IEEE754 1 #elif defined(__STDC_IEC_559__) # define UA_FLOAT_IEEE754 1 +#elif defined(ESP_PLATFORM) +# define UA_FLOAT_IEEE754 1 #else # define UA_FLOAT_IEEE754 0 #endif +#endif /* Wikipedia says (https://en.wikipedia.org/wiki/Endianness): Although the * ubiquitous x86 processors of today use little-endian storage for all types of diff --git a/include/open62541/types.h b/include/open62541/types.h index bb4f8ea7957..9ea3c3c38bb 100644 --- a/include/open62541/types.h +++ b/include/open62541/types.h @@ -1078,12 +1078,12 @@ UA_DataType_getStructMember(const UA_DataType *type, /* Test if the data type is a numeric builtin data type (via the typeKind field * of UA_DataType). This includes integers and floating point numbers. Not * included are Boolean, DateTime, StatusCode and Enums. */ -UA_Boolean +UA_Boolean UA_EXPORT UA_DataType_isNumeric(const UA_DataType *type); /* Return the Data Type Precedence-Rank defined in Part 4. * If there is no Precedence-Rank assigned with the type -1 is returned.*/ -UA_Int16 +UA_Int16 UA_EXPORT UA_DataType_getPrecedence(const UA_DataType *type); /** diff --git a/plugins/crypto/mbedtls/ua_pki_mbedtls.c b/plugins/crypto/mbedtls/ua_pki_mbedtls.c index c990ea14305..bcd4c04f720 100644 --- a/plugins/crypto/mbedtls/ua_pki_mbedtls.c +++ b/plugins/crypto/mbedtls/ua_pki_mbedtls.c @@ -3,7 +3,7 @@ * * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB * Copyright 2019 (c) Kalycito Infotech Private Limited - * Copyright 2019 (c) Julius Pfrommer, Fraunhofer IOSB + * Copyright 2019, 2024 (c) Julius Pfrommer, Fraunhofer IOSB */ #include @@ -13,14 +13,14 @@ #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS #include +#include #include #include #include +#include -#define REMOTECERTIFICATETRUSTED 1 -#define ISSUERKNOWN 2 -#define DUALPARENT 3 -#define PARENTFOUND 4 +#define UA_MBEDTLS_MAX_CHAIN_LENGTH 10 +#define UA_MBEDTLS_MAX_DN_LENGTH 256 /* Find binary substring. Taken and adjusted from * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */ @@ -42,7 +42,7 @@ UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l const unsigned char *ss2 = s2; /* handle special case */ if(l1 == 0) - return (NULL); + return NULL; if(l2 == 0) return s1; @@ -228,247 +228,272 @@ reloadCertificates(CertInfo *ci) { } } - if(internalErrorFlag) { - retval = UA_STATUSCODE_BADINTERNALERROR; - } - return retval; + return (internalErrorFlag) ? UA_STATUSCODE_BADINTERNALERROR : retval; } #endif -static UA_StatusCode -certificateVerification_verify(void *verificationContext, - const UA_ByteString *certificate) { - CertInfo *ci = (CertInfo*)verificationContext; - if(!ci) - return UA_STATUSCODE_BADINTERNALERROR; - -#ifdef __linux__ /* Reload certificates if folder paths are specified */ - UA_StatusCode certFlag = reloadCertificates(ci); - if(certFlag != UA_STATUSCODE_GOOD) { - return certFlag; - } +/* We need to access some private fields below */ +#ifndef MBEDTLS_PRIVATE +#define MBEDTLS_PRIVATE(x) x #endif - if(ci->trustListFolder.length == 0 && - ci->issuerListFolder.length == 0 && - ci->revocationListFolder.length == 0 && - ci->certificateTrustList.raw.len == 0 && - ci->certificateIssuerList.raw.len == 0 && - ci->certificateRevocationList.raw.len == 0) { - UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, - "PKI plugin unconfigured. Accepting the certificate."); - return UA_STATUSCODE_GOOD; - } - - /* Parse the certificate */ - mbedtls_x509_crt remoteCertificate; - - /* Temporary Object to parse the trustList */ - mbedtls_x509_crt *tempCert = NULL; +/* Is the certificate a CA? */ +static UA_Boolean +mbedtlsCheckCA(mbedtls_x509_crt *cert) { + /* The Basic Constraints extension must be set and the cert acts as CA */ + if(!(cert->MBEDTLS_PRIVATE(ext_types) & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) || + !cert->MBEDTLS_PRIVATE(ca_istrue)) + return false; + + /* The Key Usage extension must be set to cert signing and CRL issuing */ + if(!(cert->MBEDTLS_PRIVATE(ext_types) & MBEDTLS_X509_EXT_KEY_USAGE) || + mbedtls_x509_crt_check_key_usage(cert, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0 || + mbedtls_x509_crt_check_key_usage(cert, MBEDTLS_X509_KU_CRL_SIGN) != 0) + return false; + + return true; +} - /* Temporary Object to parse the revocationList */ - mbedtls_x509_crl *tempCrl = NULL; +static UA_Boolean +mbedtlsSameName(UA_String name, const mbedtls_x509_name *name2) { + char buf[UA_MBEDTLS_MAX_DN_LENGTH]; + int len = mbedtls_x509_dn_gets(buf, UA_MBEDTLS_MAX_DN_LENGTH, name2); + if(len < 0) + return false; + UA_String nameString = {(size_t)len, (UA_Byte*)buf}; + return UA_String_equal(&name, &nameString); +} - /* Temporary Object to identify the parent CA when there is no intermediate CA */ - mbedtls_x509_crt *parentCert = NULL; +static UA_Boolean +mbedtlsSameBuf(mbedtls_x509_buf *a, mbedtls_x509_buf *b) { + if(a->len != b->len) + return false; + return (memcmp(a->p, b->p, a->len) == 0); +} - /* Temporary Object to identify the parent CA when there is intermediate CA */ - mbedtls_x509_crt *parentCert_2 = NULL; +/* Return the first matching issuer candidate AFTER prev. + * This can return the cert itself if self-signed. */ +static mbedtls_x509_crt * +mbedtlsFindNextIssuer(CertInfo *ci, mbedtls_x509_crt *stack, + mbedtls_x509_crt *cert, mbedtls_x509_crt *prev) { + char inbuf[UA_MBEDTLS_MAX_DN_LENGTH]; + int nameLen = mbedtls_x509_dn_gets(inbuf, UA_MBEDTLS_MAX_DN_LENGTH, &cert->issuer); + if(nameLen < 0) + return NULL; + UA_String issuerName = {(size_t)nameLen, (UA_Byte*)inbuf}; + do { + for(mbedtls_x509_crt *i = stack; i; i = i->next) { + if(prev) { + if(prev == i) + prev = NULL; /* This was the last issuer we tried to verify */ + continue; + } + /* Compare issuer name and subject name. + * Skip when the key does not match the signature. */ + if(mbedtlsSameName(issuerName, &i->subject) && + mbedtls_pk_can_do(&i->pk, cert->MBEDTLS_PRIVATE(sig_pk))) + return i; + } - /* Flag value to identify if the issuer certificate is found */ - int issuerKnown = 0; + /* Switch from the stack that came with the cert to the issuer list and + * then to the trust list. */ + if(stack == &ci->certificateTrustList) + stack = NULL; + else if(stack == &ci->certificateIssuerList) + stack = &ci->certificateTrustList; + else + stack = &ci->certificateIssuerList; + } while(stack); + return NULL; +} - /* Flag value to identify if the parent certificate found */ - int parentFound = 0; +static UA_StatusCode +mbedtlsCheckRevoked(CertInfo *ci, mbedtls_x509_crt *cert) { + /* Parse the Issuer Name */ + char inbuf[UA_MBEDTLS_MAX_DN_LENGTH]; + int nameLen = mbedtls_x509_dn_gets(inbuf, UA_MBEDTLS_MAX_DN_LENGTH, &cert->issuer); + if(nameLen < 0) + return UA_STATUSCODE_BADINTERNALERROR; + UA_String issuerName = {(size_t)nameLen, (UA_Byte*)inbuf}; - mbedtls_x509_crt_init(&remoteCertificate); - int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data, - certificate->length); - if(mbedErr) { - /* char errBuff[300]; */ - /* mbedtls_strerror(mbedErr, errBuff, 300); */ - /* UA_LOG_WARNING(data->policyContext->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, */ - /* "Could not parse the remote certificate with error: %s", errBuff); */ - return UA_STATUSCODE_BADSECURITYCHECKSFAILED; + if(ci->certificateRevocationList.raw.len == 0) { + UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SECURITYPOLICY, + "Zero revocation lists have been loaded. " + "This seems intentional - omitting the check."); + return UA_STATUSCODE_GOOD; } - /* Verify */ - mbedtls_x509_crt_profile crtProfile = { - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256), - 0xFFFFFF, 0x000000, 128 * 8 // in bits - }; // TODO: remove magic numbers - - uint32_t flags = 0; - mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate, - &ci->certificateTrustList, - &ci->certificateRevocationList, - &crtProfile, NULL, &flags, NULL, NULL); - - /* Flag to check if the remote certificate is trusted or not */ - int TRUSTED = 0; - - /* Check if the remoteCertificate is present in the trustList while mbedErr value is not zero */ - if(mbedErr && !(flags & MBEDTLS_X509_BADCERT_EXPIRED) && !(flags & MBEDTLS_X509_BADCERT_FUTURE)) { - for(tempCert = &ci->certificateTrustList; tempCert != NULL; tempCert = tempCert->next) { - if(remoteCertificate.raw.len == tempCert->raw.len && - memcmp(remoteCertificate.raw.p, tempCert->raw.p, remoteCertificate.raw.len) == 0) { - TRUSTED = REMOTECERTIFICATETRUSTED; - break; - } + /* Loop over the crl and match the Issuer Name */ + UA_StatusCode res = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN; + for(mbedtls_x509_crl *crl = &ci->certificateRevocationList; crl; crl = crl->next) { + /* Is the CRL for certificates from the cert issuer? + * Is the serial number of the certificate contained in the CRL? */ + if(mbedtlsSameName(issuerName, &crl->issuer)) { + if(mbedtls_x509_crt_is_revoked(cert, crl) != 0) + return UA_STATUSCODE_BADCERTIFICATEREVOKED; + res = UA_STATUSCODE_GOOD; /* There was at least one crl that did not revoke (so far) */ } } + return res; +} - /* If the remote certificate is present in the trustList then check if the issuer certificate - * of remoteCertificate is present in issuerList */ - if(TRUSTED && mbedErr) { - mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate, - &ci->certificateIssuerList, - &ci->certificateRevocationList, - &crtProfile, NULL, &flags, NULL, NULL); - - /* Check if the parent certificate has a CRL file available */ - if(!mbedErr) { - /* Flag value to identify if that there is an intermediate CA present */ - int dualParent = 0; - - /* Identify the topmost parent certificate for the remoteCertificate */ - for(parentCert = &ci->certificateIssuerList; parentCert != NULL; parentCert = parentCert->next ) { - if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) { - for(parentCert_2 = &ci->certificateTrustList; parentCert_2 != NULL; parentCert_2 = parentCert_2->next) { - if(memcmp(parentCert->issuer_raw.p, parentCert_2->subject_raw.p, parentCert_2->subject_raw.len) == 0) { - dualParent = DUALPARENT; - break; - } - } - parentFound = PARENTFOUND; - } - - if(parentFound == PARENTFOUND) - break; - } - - /* Check if there is an intermediate certificate between the topmost parent - * certificate and child certificate - * If yes the topmost parent certificate is to be checked whether it has a - * CRL file avaiable */ - if(dualParent == DUALPARENT && parentFound == PARENTFOUND) { - parentCert = parentCert_2; - } - - /* If a parent certificate is found traverse the revocationList and identify - * if there is any CRL file that corresponds to the parentCertificate */ - if(parentFound == PARENTFOUND) { - tempCrl = &ci->certificateRevocationList; - while(tempCrl != NULL) { - if(tempCrl->version != 0 && - tempCrl->issuer_raw.len == parentCert->subject_raw.len && - memcmp(tempCrl->issuer_raw.p, - parentCert->subject_raw.p, - tempCrl->issuer_raw.len) == 0) { - issuerKnown = ISSUERKNOWN; - break; - } - - tempCrl = tempCrl->next; - } - - /* If the CRL file corresponding to the parent certificate is not present - * then return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN */ - if(!issuerKnown) { - return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN; - } - - } +/* Verify that the public key of the issuer was used to sign the certificate */ +static UA_Boolean +mbedtlsCheckSignature(const mbedtls_x509_crt *cert, mbedtls_x509_crt *issuer) { + size_t hash_len; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_type_t md = cert->MBEDTLS_PRIVATE(sig_md); +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md); + hash_len = mbedtls_md_get_size(md_info); + if(mbedtls_md(md_info, cert->tbs.p, cert->tbs.len, hash) != 0) + return false; +#else + if(psa_hash_compute(mbedtls_md_psa_alg_from_type(md), cert->tbs.p, + cert->tbs.len, hash, sizeof(hash), &hash_len) != PSA_SUCCESS) + return false; +#endif + const mbedtls_x509_buf *sig = &cert->MBEDTLS_PRIVATE(sig); + void *sig_opts = cert->MBEDTLS_PRIVATE(sig_opts); + mbedtls_pk_type_t pktype = cert->MBEDTLS_PRIVATE(sig_pk); + return (mbedtls_pk_verify_ext(pktype, sig_opts, &issuer->pk, md, + hash, hash_len, sig->p, sig->len) == 0); +} +static UA_StatusCode +mbedtlsVerifyChain(CertInfo *ci, mbedtls_x509_crt *stack, mbedtls_x509_crt **old_issuers, + mbedtls_x509_crt *cert, int depth) { + /* Maxiumum chain length */ + if(depth == UA_MBEDTLS_MAX_CHAIN_LENGTH) + return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; + + /* Verification Step: Validity Period */ + if(mbedtls_x509_time_is_future(&cert->valid_from) || + mbedtls_x509_time_is_past(&cert->valid_to)) + return (depth == 0) ? UA_STATUSCODE_BADCERTIFICATETIMEINVALID : + UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID; + + /* Return the most specific error code. BADCERTIFICATECHAININCOMPLETE is + * returned only if all possible chains are incomplete. */ + mbedtls_x509_crt *issuer = NULL; + UA_StatusCode ret = UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; + while(ret != UA_STATUSCODE_GOOD) { + /* Find the issuer. This can return the same certificate if it is + * self-signed (subject == issuer). We come back here to try a different + * "path" if a subsequent verification fails. */ + issuer = mbedtlsFindNextIssuer(ci, stack, cert, issuer); + if(!issuer) + break; + + /* Verification Step: Certificate Usage + * Can the issuer act as CA? Omit for self-signed leaf certificates. */ + if((depth > 0 || issuer != cert) && !mbedtlsCheckCA(issuer)) { + ret = UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED; + continue; } - } - else if(!mbedErr && !TRUSTED) { - /* This else if section is to identify if the parent certificate which is present in trustList - * has CRL file corresponding to it */ - - /* Identify the parent certificate of the remoteCertificate */ - for(parentCert = &ci->certificateTrustList; parentCert != NULL; parentCert = parentCert->next) { - if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) { - parentFound = PARENTFOUND; - break; - } - + /* Verification Step: Signature */ + if(!mbedtlsCheckSignature(cert, issuer)) { + ret = UA_STATUSCODE_BADCERTIFICATEINVALID; /* Wrong issuer, try again */ + continue; } - /* If the parent certificate is found traverse the revocationList and identify - * if there is any CRL file that corresponds to the parentCertificate */ - if(parentFound == PARENTFOUND && - memcmp(remoteCertificate.issuer_raw.p, remoteCertificate.subject_raw.p, remoteCertificate.subject_raw.len) != 0) { - tempCrl = &ci->certificateRevocationList; - while(tempCrl != NULL) { - if(tempCrl->version != 0 && - tempCrl->issuer_raw.len == parentCert->subject_raw.len && - memcmp(tempCrl->issuer_raw.p, - parentCert->subject_raw.p, - tempCrl->issuer_raw.len) == 0) { - issuerKnown = ISSUERKNOWN; - break; - } - - tempCrl = tempCrl->next; - } + /* The certificate is self-signed. We have arrived at the top of the + * chain. We check whether the certificate is trusted below. This is the + * only place where we return UA_STATUSCODE_BADCERTIFICATEUNTRUSTED. + * This signals that the chain is complete (but can be still + * untrusted). + * + * Break here as we have reached the end of the chain. Omit the + * Revocation Check for self-signed certificates. */ + if(issuer == cert || mbedtlsSameBuf(&cert->tbs, &issuer->tbs)) { + ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED; + break; + } - /* If the CRL file corresponding to the parent certificate is not present - * then return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN */ - if(!issuerKnown) { - return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN; - } + /* Verification Step: Revocation Check */ + ret = mbedtlsCheckRevoked(ci, cert); + if(depth > 0) { + if(ret == UA_STATUSCODE_BADCERTIFICATEREVOKED) + ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED; + if(ret == UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN) + ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN; + } + if(ret != UA_STATUSCODE_GOOD) + continue; + /* Detect (endless) loops of issuers */ + for(int i = 0; i < depth; i++) { + if(old_issuers[i] == issuer) + return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; } + old_issuers[depth] = issuer; + /* We have found the issuer certificate used for the signature. Recurse + * to the next certificate in the chain (verify the current issuer). */ + ret = mbedtlsVerifyChain(ci, stack, old_issuers, issuer, depth + 1); } - // TODO: Extend verification - - /* This condition will check whether the certificate is a User certificate - * or a CA certificate. If the MBEDTLS_X509_KU_KEY_CERT_SIGN and - * MBEDTLS_X509_KU_CRL_SIGN of key_usage are set, then the certificate - * shall be condidered as CA Certificate and cannot be used to establish a - * connection. Refer the test case CTT/Security/Security Certificate Validation/029.js - * for more details */ -#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 - if((remoteCertificate.key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) && - (remoteCertificate.key_usage & MBEDTLS_X509_KU_CRL_SIGN)) { - return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; - } -#else - if((remoteCertificate.private_key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) && - (remoteCertificate.private_key_usage & MBEDTLS_X509_KU_CRL_SIGN)) { - return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; + /* The chain is complete, but we haven't yet identified a trusted + * certificate "on the way down". Can we trust this certificate? */ + if(ret == UA_STATUSCODE_BADCERTIFICATEUNTRUSTED) { + for(mbedtls_x509_crt *t = &ci->certificateTrustList; t; t = t->next) { + if(mbedtlsSameBuf(&cert->tbs, &t->tbs)) + return UA_STATUSCODE_GOOD; + } } -#endif + return ret; +} - UA_StatusCode retval = UA_STATUSCODE_GOOD; - if(mbedErr) { -#if UA_LOGLEVEL <= 400 - char buff[100]; - int len = mbedtls_x509_crt_verify_info(buff, 100, "", flags); - UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SECURITYPOLICY, - "Verifying the certificate failed with error: %.*s", len-1, buff); +/* This follows Part 6, 6.1.3 Determining if a Certificate is trusted. + * It defines a sequence of steps for certificate verification. */ +static UA_StatusCode +certificateVerification_verify(void *verificationContext, + const UA_ByteString *certificate) { + if(!verificationContext || !certificate) + return UA_STATUSCODE_BADINTERNALERROR; + + UA_StatusCode ret = UA_STATUSCODE_GOOD; + CertInfo *ci = (CertInfo*)verificationContext; + +#ifdef __linux__ /* Reload certificates if folder paths are specified */ + ret = reloadCertificates(ci); + if(ret != UA_STATUSCODE_GOOD) + return ret; #endif - if(flags & (uint32_t)MBEDTLS_X509_BADCERT_NOT_TRUSTED) { - retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED; - } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_FUTURE || - flags & (uint32_t)MBEDTLS_X509_BADCERT_EXPIRED) { - retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID; - } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_REVOKED || - flags & (uint32_t)MBEDTLS_X509_BADCRL_EXPIRED) { - retval = UA_STATUSCODE_BADCERTIFICATEREVOKED; - } else { - retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; - } + + /* Verification Step: Certificate Structure + * This parses the entire certificate chain contained in the bytestring. */ + mbedtls_x509_crt cert; + mbedtls_x509_crt_init(&cert); + int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, + certificate->length); + if(mbedErr) + return UA_STATUSCODE_BADCERTIFICATEINVALID; + + /* Verification Step: Certificate Usage + * Check whether the certificate is a User certificate or a CA certificate. + * Refer the test case CTT/Security/Security Certificate Validation/029.js + * for more details. */ + if(mbedtlsCheckCA(&cert)) { + mbedtls_x509_crt_free(&cert); + return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; } - mbedtls_x509_crt_free(&remoteCertificate); - return retval; + /* These steps are performed outside of this method. + * Because we need the server or client context. + * - Security Policy + * - Host Name + * - URI */ + + /* Verification Step: Build Certificate Chain + * We perform the checks for each certificate inside. */ + mbedtls_x509_crt *old_issuers[UA_MBEDTLS_MAX_CHAIN_LENGTH]; + ret = mbedtlsVerifyChain(ci, &cert, old_issuers, &cert, 0); + mbedtls_x509_crt_free(&cert); + return ret; } static UA_StatusCode @@ -607,4 +632,5 @@ UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv, } #endif -#endif + +#endif /* UA_ENABLE_ENCRYPTION_MBEDTLS */ diff --git a/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c b/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c index e708c78fdc1..5ede408d31b 100644 --- a/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c +++ b/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c @@ -746,6 +746,10 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString l memset(policy, 0, sizeof(UA_SecurityPolicy)); policy->logger = logger; + UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURITYPOLICY, + "!! WARNING !! The Basic128Rsa15 SecurityPolicy is unsecure. " + "There are known attacks that break the encryption."); + policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0"); UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; diff --git a/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c b/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c index bf0196bb7f8..fd4ddc008a4 100644 --- a/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c +++ b/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c @@ -667,6 +667,11 @@ policyContext_newContext_sp_basic256(UA_SecurityPolicy *securityPolicy, UA_StatusCode UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localCertificate, const UA_ByteString localPrivateKey, const UA_Logger *logger) { + + UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURITYPOLICY, + "!! WARNING !! The Basic256 SecurityPolicy is unsecure. " + "There are known attacks that break the encryption."); + memset(policy, 0, sizeof(UA_SecurityPolicy)); policy->logger = logger; diff --git a/plugins/crypto/openssl/ua_openssl_basic128rsa15.c b/plugins/crypto/openssl/ua_openssl_basic128rsa15.c index 71affd31655..7e47e4d0729 100644 --- a/plugins/crypto/openssl/ua_openssl_basic128rsa15.c +++ b/plugins/crypto/openssl/ua_openssl_basic128rsa15.c @@ -500,6 +500,10 @@ UA_SecurityPolicy_Basic128Rsa15 (UA_SecurityPolicy * policy, const UA_ByteString localPrivateKey, const UA_Logger * logger) { + UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURITYPOLICY, + "!! WARNING !! The Basic128Rsa15 SecurityPolicy is unsecure. " + "There are known attacks that break the encryption."); + UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule; UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule; UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule; diff --git a/plugins/crypto/openssl/ua_openssl_basic256.c b/plugins/crypto/openssl/ua_openssl_basic256.c index e54042a7a02..a3c8903364c 100644 --- a/plugins/crypto/openssl/ua_openssl_basic256.c +++ b/plugins/crypto/openssl/ua_openssl_basic256.c @@ -501,6 +501,11 @@ UA_SecurityPolicy_Basic256 (UA_SecurityPolicy * policy, const UA_ByteString localCertificate, const UA_ByteString localPrivateKey, const UA_Logger * logger) { + + UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURITYPOLICY, + "!! WARNING !! The Basic256 SecurityPolicy is unsecure. " + "There are known attacks that break the encryption."); + UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule; UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule; UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule; diff --git a/plugins/crypto/openssl/ua_openssl_version_abstraction.h b/plugins/crypto/openssl/ua_openssl_version_abstraction.h index a6fa45bdf70..c3eb7fd7dc5 100644 --- a/plugins/crypto/openssl/ua_openssl_version_abstraction.h +++ b/plugins/crypto/openssl/ua_openssl_version_abstraction.h @@ -21,11 +21,11 @@ #define X509_STORE_CTX_set0_trusted_stack(STORE_CTX, CTX_SKTRUSTED) X509_STORE_CTX_trusted_stack(STORE_CTX, CTX_SKTRUSTED) #endif -#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER < 0x1010000fL || ( defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050000fL) #define X509_STORE_CTX_get_check_issued(STORE_CTX) STORE_CTX->check_issued #endif -#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER < 0x1010000fL || ( defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050000fL) #define get_pkey_rsa(evp) ((evp)->pkey.rsa) #else #define get_pkey_rsa(evp) EVP_PKEY_get0_RSA(evp) diff --git a/plugins/crypto/openssl/ua_pki_openssl.c b/plugins/crypto/openssl/ua_pki_openssl.c index d85f4617a5f..1ad5c1fc909 100644 --- a/plugins/crypto/openssl/ua_pki_openssl.c +++ b/plugins/crypto/openssl/ua_pki_openssl.c @@ -118,9 +118,7 @@ UA_CertificateVerification_clear (UA_CertificateVerification * cv) { UA_CertContext_sk_free (context); UA_free (context); - cv->context = NULL; - - return; + memset(cv, 0, sizeof(UA_CertificateVerification)); } static UA_StatusCode @@ -314,6 +312,10 @@ UA_ReloadCertFromFolder (CertContext * ctx) { } UA_ByteString_clear (&strCert); } + for (i = 0; i < numCertificates; i++) { + free(dirlist[i]); + } + free(dirlist); } if (ctx->issuerListFolder.length > 0) { @@ -349,6 +351,10 @@ UA_ReloadCertFromFolder (CertContext * ctx) { } UA_ByteString_clear (&strCert); } + for (i = 0; i < numCertificates; i++) { + free(dirlist[i]); + } + free(dirlist); } if (ctx->revocationListFolder.length > 0) { @@ -384,6 +390,10 @@ UA_ReloadCertFromFolder (CertContext * ctx) { } UA_ByteString_clear (&strCert); } + for (i = 0; i < numCertificates; i++) { + free(dirlist[i]); + } + free(dirlist); } ret = UA_STATUSCODE_GOOD; @@ -392,192 +402,282 @@ UA_ReloadCertFromFolder (CertContext * ctx) { #endif /* end of __linux__ */ -static UA_StatusCode -UA_X509_Store_CTX_Error_To_UAError (int opensslErr) { - UA_StatusCode ret; - - switch (opensslErr) { - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_CRL_NOT_YET_VALID: - case X509_V_ERR_CRL_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - ret = UA_STATUSCODE_BADCERTIFICATETIMEINVALID; - break; - case X509_V_ERR_CERT_REVOKED: - ret = UA_STATUSCODE_BADCERTIFICATEREVOKED; - break; - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED; - break; - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - ret = UA_STATUSCODE_BADSECURITYCHECKSFAILED; - break; - case X509_V_ERR_UNABLE_TO_GET_CRL: - ret = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN; - break; - default: - ret = UA_STATUSCODE_BADCERTIFICATEINVALID; - break; - } - return ret; - } +static const unsigned char openssl_PEM_PRE[28] = "-----BEGIN CERTIFICATE-----"; + +/* Extract the leaf certificate from a bytestring that may contain an entire chain */ +static X509 * +openSSLLoadLeafCertificate(UA_ByteString cert, size_t *offset) { + if(cert.length <= *offset) + return NULL; + cert.length -= *offset; + cert.data += *offset; + + /* Detect DER encoding. Extract the encoding length and cut. */ + if(cert.length >= 4 && cert.data[0] == 0x30 && cert.data[1] == 0x82) { + /* The certificate length is encoded after the magic bytes */ + size_t certLen = 4; /* Magic numbers + length bytes */ + certLen += (size_t)(((uint16_t)cert.data[2]) << 8); + certLen += cert.data[3]; + if(certLen > cert.length) + return NULL; + cert.length = certLen; + *offset += certLen; + const UA_Byte *dataPtr = cert.data; + return d2i_X509(NULL, &dataPtr, (long)cert.length); + } + + /* Assume PEM encoding. Detect multiple certificates and cut. */ + if(cert.length > 27 * 4) { + const unsigned char *match = + UA_Bstrstr(openssl_PEM_PRE, 27, &cert.data[27*2], cert.length - (27*2)); + if(match) + cert.length = (uintptr_t)(match - cert.data); + } + *offset += cert.length; + + BIO *bio = BIO_new_mem_buf((void *) cert.data, (int)cert.length); + X509 *result = PEM_read_bio_X509(bio, NULL, NULL, NULL); + BIO_free(bio); + return result; +} -static UA_StatusCode -UA_CertificateVerification_Verify (void * verificationContext, - const UA_ByteString * certificate) { - X509_STORE_CTX* storeCtx; - X509_STORE* store; - CertContext * ctx; - UA_StatusCode ret; - int opensslRet; - X509 * certificateX509 = NULL; +/* The bytestring might contain an entire certificate chain. The first + * stack-element is the leaf certificate itself. The remaining ones are + * potential issuer certificates. */ +static STACK_OF(X509) * +openSSLLoadCertificateStack(const UA_ByteString cert) { + size_t offset = 0; + X509 *x509 = NULL; + STACK_OF(X509) *result = sk_X509_new_null(); + if(!result) + return NULL; + while((x509 = openSSLLoadLeafCertificate(cert, &offset))) { + sk_X509_push(result, x509); + } + return result; +} - if (verificationContext == NULL) { - return UA_STATUSCODE_BADINTERNALERROR; - } - ctx = (CertContext *) verificationContext; - - store = X509_STORE_new(); - storeCtx = X509_STORE_CTX_new(); - - if (store == NULL || storeCtx == NULL) { - ret = UA_STATUSCODE_BADOUTOFMEMORY; - goto cleanup; - } -#ifdef __linux__ - ret = UA_ReloadCertFromFolder (ctx); - if (ret != UA_STATUSCODE_GOOD) { - goto cleanup; - } -#endif +/* Return the first matching issuer candidate AFTER prev */ +static X509 * +openSSLFindNextIssuer(CertContext *ctx, STACK_OF(X509) *stack, X509 *x509, X509 *prev) { + /* First check issuers from the stack - provided in the same bytestring as + * the certificate. This can also return x509 itself. */ + do { + int size = sk_X509_num(stack); + for(int i = 0; i < size; i++) { + X509 *candidate = sk_X509_value(stack, i); + if(prev) { + if(prev == candidate) + prev = NULL; /* This was the last issuer we tried to verify */ + continue; + } + /* This checks subject/issuer name and the key usage of the issuer. + * It does not verify the validity period and if the issuer key was + * used for the signature. We check that afterwards. */ + if(X509_check_issued(candidate, x509) == 0) + return candidate; + } + /* Switch from the stack that came with the cert to the issuer list and + * then to the trust list. */ + if(stack == ctx->skTrusted) + stack = NULL; + else if(stack == ctx->skIssue) + stack = ctx->skTrusted; + else + stack = ctx->skIssue; + } while(stack); + return NULL; +} - certificateX509 = UA_OpenSSL_LoadCertificate(certificate); - if (certificateX509 == NULL) { - ret = UA_STATUSCODE_BADCERTIFICATEINVALID; - goto cleanup; - } - - X509_STORE_set_flags(store, 0); - opensslRet = X509_STORE_CTX_init (storeCtx, store, certificateX509, - ctx->skIssue); - if (opensslRet != 1) { - ret = UA_STATUSCODE_BADINTERNALERROR; - goto cleanup; - } -#if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT < 0x10100000L - (void) X509_STORE_CTX_trusted_stack (storeCtx, ctx->skTrusted); -#else - (void) X509_STORE_CTX_set0_trusted_stack (storeCtx, ctx->skTrusted); -#endif +/* Is the certificate a CA? */ +static UA_Boolean +openSSLCheckCA(X509 *cert) { + uint32_t flags = X509_get_extension_flags(cert); + /* The basic constraints must be set with the CA flag true */ + if(!(flags & EXFLAG_CA)) + return false; - /* Set crls to ctx */ - if (sk_X509_CRL_num (ctx->skCrls) > 0) { - X509_STORE_CTX_set0_crls (storeCtx, ctx->skCrls); - } + /* The Key Usage extension must be set */ + if(!(flags & EXFLAG_KUSAGE)) + return false; - /* Set flag to check if the certificate has an invalid signature */ - X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CHECK_SS_SIGNATURE); + /* The Key Usage must include cert signing and CRL issuing */ + uint32_t usage = X509_get_key_usage(cert); + if(!(usage & KU_KEY_CERT_SIGN) || !(usage & KU_CRL_SIGN)) + return false; - if (X509_STORE_CTX_get_check_issued(storeCtx) (storeCtx,certificateX509, certificateX509) != 1) { - X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CRL_CHECK); - } + return true; +} - /* This condition will check whether the certificate is a User certificate or a CA certificate. - * If the KU_KEY_CERT_SIGN and KU_CRL_SIGN of key_usage are set, then the certificate shall be - * condidered as CA Certificate and cannot be used to establish a connection. Refer the test case - * CTT/Security/Security Certificate Validation/029.js for more details */ - /** \todo Can the ca-parameter of X509_check_purpose can be used? */ - if(X509_check_purpose(certificateX509, X509_PURPOSE_CRL_SIGN, 0) && X509_check_ca(certificateX509)) { - return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; +static UA_StatusCode +openSSLCheckRevoked(CertContext *ctx, X509 *cert) { + const ASN1_INTEGER *sn = X509_get0_serialNumber(cert); + const X509_NAME *in = X509_get_issuer_name(cert); + int size = sk_X509_CRL_num(ctx->skCrls); + + if(size == 0) { + UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SECURITYPOLICY, + "Zero revocation lists have been loaded. " + "This seems intentional - omitting the check."); + return UA_STATUSCODE_GOOD; + } + + /* Loop over the crl and match the Issuer Name */ + UA_StatusCode res = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN; + for(int i = 0; i < size; i++) { + /* The crl contains a list of serial numbers from the same issuer */ + X509_CRL *crl = sk_X509_CRL_value(ctx->skCrls, i); + if(X509_NAME_cmp(in, X509_CRL_get_issuer(crl)) != 0) + continue; + STACK_OF(X509_REVOKED) *rs = X509_CRL_get_REVOKED(crl); + int rsize = sk_X509_REVOKED_num(rs); + for(int j = 0; j < rsize; j++) { + X509_REVOKED *r = sk_X509_REVOKED_value(rs, j); + if(ASN1_INTEGER_cmp(sn, X509_REVOKED_get0_serialNumber(r)) == 0) + return UA_STATUSCODE_BADCERTIFICATEREVOKED; + } + res = UA_STATUSCODE_GOOD; /* There was at least one crl that did not revoke (so far) */ } + return res; +} - opensslRet = X509_verify_cert (storeCtx); - if (opensslRet == 1) { - ret = UA_STATUSCODE_GOOD; +#define UA_OPENSSL_MAX_CHAIN_LENGTH 10 - /* Check if the not trusted certificate has a CRL file. If there is no CRL file available for the corresponding - * parent certificate then return status code UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN. Refer the test - * case CTT/Security/Security Certificate Validation/002.js */ - if (X509_STORE_CTX_get_check_issued (storeCtx) (storeCtx,certificateX509, certificateX509) != 1) { - /* Free X509_STORE_CTX and reuse it for certification verification */ - if (storeCtx != NULL) { - X509_STORE_CTX_free(storeCtx); - } +static UA_StatusCode +openSSL_verifyChain(CertContext *ctx, STACK_OF(X509) *stack, X509 **old_issuers, + X509 *cert, int depth) { + /* Maxiumum chain length */ + if(depth == UA_OPENSSL_MAX_CHAIN_LENGTH) + return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; + + /* Verification Step: Validity Period */ + ASN1_TIME *notBefore = X509_get_notBefore(cert); + ASN1_TIME *notAfter = X509_get_notAfter(cert); + if(X509_cmp_current_time(notBefore) != -1 || X509_cmp_current_time(notAfter) != 1) + return (depth == 0) ? UA_STATUSCODE_BADCERTIFICATETIMEINVALID : + UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID; + + /* Return the most specific error code. BADCERTIFICATECHAININCOMPLETE is + * returned only if all possible chains are incomplete. */ + X509 *issuer = NULL; + UA_StatusCode ret = UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; + while(ret != UA_STATUSCODE_GOOD) { + /* Find the issuer. We jump back here to find a different path if a + * subsequent check fails. */ + issuer = openSSLFindNextIssuer(ctx, stack, cert, issuer); + if(!issuer) + break; - /* Initialised X509_STORE_CTX sructure*/ - storeCtx = X509_STORE_CTX_new(); + /* Verification Step: Certificate Usage + * Can the issuer act as CA? Omit for self-signed leaf certificates. */ + if((depth > 0 || issuer != cert) && !openSSLCheckCA(issuer)) { + ret = UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED; + continue; + } - /* Sets up X509_STORE_CTX structure for a subsequent verification operation */ - X509_STORE_set_flags(store, 0); - X509_STORE_CTX_init (storeCtx, store, certificateX509,ctx->skIssue); + /* Verification Step: Signature */ + int opensslRet = X509_verify(cert, X509_get0_pubkey(issuer)); + if(opensslRet == -1) { + return UA_STATUSCODE_BADCERTIFICATEINVALID; /* Ill-formed signature */ + } else if(opensslRet == 0) { + ret = UA_STATUSCODE_BADCERTIFICATEINVALID; /* Wrong issuer, try again */ + continue; + } - /* Set trust list to ctx */ - (void) X509_STORE_CTX_trusted_stack (storeCtx, ctx->skTrusted); + /* The certificate is self-signed. We have arrived at the top of the + * chain. We check whether the certificate is trusted below. This is the + * only place where we return UA_STATUSCODE_BADCERTIFICATEUNTRUSTED. + * This signals that the chain is complete (but can be still + * untrusted). + * + * Break here as we have reached the end of the chain. Omit the + * Revocation Check for self-signed certificates. */ + if(cert == issuer || X509_cmp(cert, issuer) == 0) { + ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED; + break; + } - /* Set crls to ctx */ - X509_STORE_CTX_set0_crls (storeCtx, ctx->skCrls); + /* Verification Step: Revocation Check */ + ret = openSSLCheckRevoked(ctx, cert); + if(depth > 0) { + if(ret == UA_STATUSCODE_BADCERTIFICATEREVOKED) + ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED; + if(ret == UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN) + ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN; + } + if(ret != UA_STATUSCODE_GOOD) + continue; + + /* Detect (endless) loops of issuers. The last one can be skipped by the + * check for self-signed just before. */ + for(int i = 0; i < depth; i++) { + if(old_issuers[i] == issuer) + return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; + } + old_issuers[depth] = issuer; - /* Set flags for CRL check */ - X509_STORE_CTX_set_flags (storeCtx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + /* We have found the issuer certificate used for the signature. Recurse + * to the next certificate in the chain (verify the current issuer). */ + ret = openSSL_verifyChain(ctx, stack, old_issuers, issuer, depth + 1); + } - opensslRet = X509_verify_cert (storeCtx); - if (opensslRet != 1) { - opensslRet = X509_STORE_CTX_get_error (storeCtx); - if (opensslRet == X509_V_ERR_UNABLE_TO_GET_CRL) { - ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN; - } - } + /* Is the certificate in the trust list? If yes, then we are done. */ + if(ret == UA_STATUSCODE_BADCERTIFICATEUNTRUSTED) { + for(int i = 0; i < sk_X509_num(ctx->skTrusted); i++) { + if(X509_cmp(cert, sk_X509_value(ctx->skTrusted, i)) == 0) + return UA_STATUSCODE_GOOD; } } - else { - opensslRet = X509_STORE_CTX_get_error (storeCtx); - - /* Check the issued certificate of a CA that is not trusted but available */ - if(opensslRet == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN){ - int trusted_cert_len = sk_X509_num(ctx->skTrusted); - int cmpVal; - X509 *trusted_cert; - const ASN1_OCTET_STRING *trusted_cert_keyid; - const ASN1_OCTET_STRING *remote_cert_keyid; - for (int i = 0; i < trusted_cert_len; i++) { - trusted_cert = sk_X509_value(ctx->skTrusted, i); + return ret; +} - /* Fetch the Subject key identifier of the certificate in trust list */ - trusted_cert_keyid = X509_get0_subject_key_id(trusted_cert); +/* This follows Part 6, 6.1.3 Determining if a Certificate is trusted. + * It defines a sequence of steps for certificate verification. */ +static UA_StatusCode +UA_CertificateVerification_Verify(void *verificationContext, + const UA_ByteString *certificate) { + if(!verificationContext || !certificate) + return UA_STATUSCODE_BADINTERNALERROR; - /* Fetch the Subject key identifier of the remote certificate */ - remote_cert_keyid = X509_get0_subject_key_id(certificateX509); + UA_StatusCode ret = UA_STATUSCODE_GOOD; + CertContext *ctx = (CertContext *)verificationContext; - /* Check remote certificate is present in the trust list */ - cmpVal = ASN1_OCTET_STRING_cmp(trusted_cert_keyid, remote_cert_keyid); - if (cmpVal == 0){ - ret = UA_STATUSCODE_GOOD; - goto cleanup; - } - } - } +#ifdef __linux__ + ret = UA_ReloadCertFromFolder(ctx); + if(ret != UA_STATUSCODE_GOOD) + return ret; +#endif - /* Return expected OPCUA error code */ - ret = UA_X509_Store_CTX_Error_To_UAError (opensslRet); - } -cleanup: - if (store != NULL) { - X509_STORE_free (store); - } - if (storeCtx != NULL) { - X509_STORE_CTX_free (storeCtx); - } - if (certificateX509 != NULL) { - X509_free (certificateX509); + /* Verification Step: Certificate Structure */ + STACK_OF(X509) *stack = openSSLLoadCertificateStack(*certificate); + if(!stack || sk_X509_num(stack) < 1) { + if(stack) + sk_X509_pop_free(stack, X509_free); + return UA_STATUSCODE_BADCERTIFICATEINVALID; + } + + /* Verification Step: Certificate Usage + * Check whether the certificate is a User certificate or a CA certificate. + * Refer the test case CTT/Security/Security Certificate Validation/029.js + * for more details. */ + X509 *leaf = sk_X509_value(stack, 0); + if(openSSLCheckCA(leaf)) { + sk_X509_pop_free(stack, X509_free); + return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; } + + /* These steps are performed outside of this method. + * Because we need the server or client context. + * - Security Policy + * - Host Name + * - URI */ + + /* Verification Step: Build Certificate Chain + * We perform the checks for each certificate inside. */ + X509 *old_issuers[UA_OPENSSL_MAX_CHAIN_LENGTH]; + ret = openSSL_verifyChain(ctx, stack, old_issuers, leaf, 0); + sk_X509_pop_free(stack, X509_free); return ret; } diff --git a/plugins/ua_accesscontrol_default.c b/plugins/ua_accesscontrol_default.c index c3e9183486e..bc11203d7c0 100644 --- a/plugins/ua_accesscontrol_default.c +++ b/plugins/ua_accesscontrol_default.c @@ -53,6 +53,13 @@ activateSession_default(UA_Server *server, UA_AccessControl *ac, /* No userdata atm */ *sessionContext = NULL; + + /* Set the clientUserId to the empty string for anonymous */ + UA_String emptyStr = UA_STRING_NULL; + UA_Variant userIdVar; + UA_Variant_setScalar(&userIdVar, &emptyStr, &UA_TYPES[UA_TYPES_STRING]); + UA_Server_setSessionParameter(server, sessionId, "clientUserId", &userIdVar); + return UA_STATUSCODE_GOOD; } @@ -76,6 +83,13 @@ activateSession_default(UA_Server *server, UA_AccessControl *ac, /* No userdata atm */ *sessionContext = NULL; + + /* Set the clientUserId to the empty string for anonymous */ + UA_String emptyStr = UA_STRING_NULL; + UA_Variant userIdVar; + UA_Variant_setScalar(&userIdVar, &emptyStr, &UA_TYPES[UA_TYPES_STRING]); + UA_Server_setSessionParameter(server, sessionId, "clientUserId", &userIdVar); + return UA_STATUSCODE_GOOD; } @@ -99,8 +113,8 @@ activateSession_default(UA_Server *server, UA_AccessControl *ac, UA_Boolean match = false; if(context->loginCallback) { if(context->loginCallback(&userToken->userName, &userToken->password, - context->usernamePasswordLoginSize, context->usernamePasswordLogin, - sessionContext, context->loginContext) == UA_STATUSCODE_GOOD) + context->usernamePasswordLoginSize, context->usernamePasswordLogin, + sessionContext, context->loginContext) == UA_STATUSCODE_GOOD) match = true; } else { for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) { @@ -114,11 +128,10 @@ activateSession_default(UA_Server *server, UA_AccessControl *ac, if(!match) return UA_STATUSCODE_BADUSERACCESSDENIED; - /* For the CTT, recognize whether two sessions are */ - UA_ByteString *username = UA_ByteString_new(); - if(username) - UA_ByteString_copy(&userToken->userName, username); - *sessionContext = username; + /* Set the clientUserId to the username */ + UA_Variant userIdVar; + UA_Variant_setScalar(&userIdVar, (void*)(uintptr_t)&userToken->userName, &UA_TYPES[UA_TYPES_STRING]); + UA_Server_setSessionParameter(server, sessionId, "clientUserId", &userIdVar); return UA_STATUSCODE_GOOD; } @@ -133,9 +146,18 @@ activateSession_default(UA_Server *server, UA_AccessControl *ac, if(!context->verifyX509.verifyCertificate) return UA_STATUSCODE_BADIDENTITYTOKENINVALID; - return context->verifyX509. + UA_Boolean verified = + context->verifyX509. verifyCertificate(context->verifyX509.context, &userToken->certificateData); + if(!verified) + return false; + + /* Set the clientUserId to the certificate data */ + UA_Variant userIdVar; + UA_Variant_setScalar(&userIdVar, (void*)(uintptr_t)&userToken->certificateData, &UA_TYPES[UA_TYPES_BYTESTRING]); + UA_Server_setSessionParameter(server, sessionId, "clientUserId", &userIdVar); + return true; } /* Unsupported token type */ @@ -145,8 +167,6 @@ activateSession_default(UA_Server *server, UA_AccessControl *ac, static void closeSession_default(UA_Server *server, UA_AccessControl *ac, const UA_NodeId *sessionId, void *sessionContext) { - if(sessionContext) - UA_ByteString_delete((UA_ByteString*)sessionContext); } static UA_UInt32 @@ -218,12 +238,20 @@ static UA_Boolean allowTransferSubscription_default(UA_Server *server, UA_AccessControl *ac, const UA_NodeId *oldSessionId, void *oldSessionContext, const UA_NodeId *newSessionId, void *newSessionContext) { - if(oldSessionContext == newSessionContext) - return true; - if(oldSessionContext && newSessionContext) - return UA_ByteString_equal((UA_ByteString*)oldSessionContext, - (UA_ByteString*)newSessionContext); - return false; + UA_Variant userId1; + UA_Variant userId2; + UA_Variant_init(&userId1); + UA_Variant_init(&userId2); + + UA_StatusCode res = UA_STATUSCODE_GOOD; + res |= UA_Server_getSessionParameter(server, oldSessionId, "userClientId", &userId1); + res |= UA_Server_getSessionParameter(server, newSessionId, "userClientId", &userId2); + + UA_Boolean allow = (res == UA_STATUSCODE_GOOD && + UA_order(&userId1, &userId2, &UA_TYPES[UA_TYPES_VARIANT]) == UA_ORDER_EQ); + UA_Variant_clear(&userId1); + UA_Variant_clear(&userId2); + return allow; } #endif diff --git a/plugins/ua_config_default.c b/plugins/ua_config_default.c index c4c8f4ffec7..01c21455919 100644 --- a/plugins/ua_config_default.c +++ b/plugins/ua_config_default.c @@ -184,6 +184,8 @@ setDefaultConfig(UA_ServerConfig *conf) { /* Certificate Verification that accepts every certificate. Can be * overwritten when the policy is specialized. */ + if(conf->certificateVerification.clear) + conf->certificateVerification.clear(&conf->certificateVerification); UA_CertificateVerification_AcceptAll(&conf->certificateVerification); /* * Global Node Lifecycle * */ @@ -209,6 +211,7 @@ setDefaultConfig(UA_ServerConfig *conf) { conf->maxNotificationsPerPublish = 1000; conf->enableRetransmissionQueue = true; conf->maxRetransmissionQueueSize = 0; /* unlimited */ + conf->maxPublishReqPerSession = 512; /* limit outstanding publish requests per session */ # ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS conf->maxEventsPerNode = 0; /* unlimited */ # endif @@ -637,19 +640,21 @@ UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config, UA_StatusCode_name(retval)); } - retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, &localCertificate, &localPrivateKey); - if(retval != UA_STATUSCODE_GOOD) { - UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, - "Could not add SecurityPolicy#Basic128Rsa15 with error code %s", - UA_StatusCode_name(retval)); - } + /* Basic128Rsa15 should no longer be used */ + /* retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, &localCertificate, &localPrivateKey); */ + /* if(retval != UA_STATUSCODE_GOOD) { */ + /* UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, */ + /* "Could not add SecurityPolicy#Basic128Rsa15 with error code %s", */ + /* UA_StatusCode_name(retval)); */ + /* } */ - retval = UA_ServerConfig_addSecurityPolicyBasic256(config, &localCertificate, &localPrivateKey); - if(retval != UA_STATUSCODE_GOOD) { - UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, - "Could not add SecurityPolicy#Basic256 with error code %s", - UA_StatusCode_name(retval)); - } + /* Basic256 should no longer be used */ + /* retval = UA_ServerConfig_addSecurityPolicyBasic256(config, &localCertificate, &localPrivateKey); */ + /* if(retval != UA_STATUSCODE_GOOD) { */ + /* UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, */ + /* "Could not add SecurityPolicy#Basic256 with error code %s", */ + /* UA_StatusCode_name(retval)); */ + /* } */ retval = UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, &localCertificate, &localPrivateKey); if(retval != UA_STATUSCODE_GOOD) { @@ -685,6 +690,8 @@ UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf, return retval; } + if(conf->certificateVerification.clear) + conf->certificateVerification.clear(&conf->certificateVerification); retval = UA_CertificateVerification_Trustlist(&conf->certificateVerification, trustList, trustListSize, issuerList, issuerListSize, @@ -758,6 +765,8 @@ UA_ClientConfig_setDefault(UA_ClientConfig *config) { /* Certificate Verification that accepts every certificate. Can be * overwritten when the policy is specialized. */ + if(config->certificateVerification.clear) + config->certificateVerification.clear(&config->certificateVerification); UA_CertificateVerification_AcceptAll(&config->certificateVerification); UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, "AcceptAll Certificate Verification. " @@ -816,6 +825,8 @@ UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config, if(retval != UA_STATUSCODE_GOOD) return retval; + if(config->certificateVerification.clear) + config->certificateVerification.clear(&config->certificateVerification); retval = UA_CertificateVerification_Trustlist(&config->certificateVerification, trustList, trustListSize, NULL, 0, @@ -830,25 +841,27 @@ UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config, return UA_STATUSCODE_BADOUTOFMEMORY; config->securityPolicies = sp; - retval = UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize], - localCertificate, privateKey, &config->logger); - if(retval == UA_STATUSCODE_GOOD) { - ++config->securityPoliciesSize; - } else { - UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, - "Could not add SecurityPolicy#Basic128Rsa15 with error code %s", - UA_StatusCode_name(retval)); - } - - retval = UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize], - localCertificate, privateKey, &config->logger); - if(retval == UA_STATUSCODE_GOOD) { - ++config->securityPoliciesSize; - } else { - UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, - "Could not add SecurityPolicy#Basic256 with error code %s", - UA_StatusCode_name(retval)); - } + /* Basic128Rsa15 should no longer be used */ + /* retval = UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize], */ + /* localCertificate, privateKey, &config->logger); */ + /* if(retval == UA_STATUSCODE_GOOD) { */ + /* ++config->securityPoliciesSize; */ + /* } else { */ + /* UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, */ + /* "Could not add SecurityPolicy#Basic128Rsa15 with error code %s", */ + /* UA_StatusCode_name(retval)); */ + /* } */ + + /* Basic256 should no longer be used */ + /* retval = UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize], */ + /* localCertificate, privateKey, &config->logger); */ + /* if(retval == UA_STATUSCODE_GOOD) { */ + /* ++config->securityPoliciesSize; */ + /* } else { */ + /* UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, */ + /* "Could not add SecurityPolicy#Basic256 with error code %s", */ + /* UA_StatusCode_name(retval)); */ + /* } */ retval = UA_SecurityPolicy_Basic256Sha256(&config->securityPolicies[config->securityPoliciesSize], localCertificate, privateKey, &config->logger); diff --git a/src/client/ua_client.c b/src/client/ua_client.c index 778d1a6365d..cca789eaaa7 100644 --- a/src/client/ua_client.c +++ b/src/client/ua_client.c @@ -436,8 +436,14 @@ receiveResponse(UA_Client *client, void *response, const UA_DataType *responseTy UA_LOG_WARNING_CHANNEL(&client->config.logger, &client->channel, "Receiving the response failed with StatusCode %s", UA_StatusCode_name(retval)); + /* The receive itself can succeed while the channel was closed + * remotely (e.g. an ERR message during the handshake). Forward the + * detailed status code captured from the close so the reconnect is + * not silent. */ + if(retval == UA_STATUSCODE_GOOD) + retval = (client->connectStatus != UA_STATUSCODE_GOOD) ? + client->connectStatus : UA_STATUSCODE_BADCONNECTIONCLOSED; closeSecureChannel(client); - retval = UA_STATUSCODE_BADCONNECTIONCLOSED; break; } now = UA_DateTime_nowMonotonic(); @@ -515,8 +521,17 @@ UA_Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac, } void UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode) { + /* Make this function reentrant. One of the async callbacks could indirectly + * operate on the list. Moving all elements to a local list before iterating + * that. */ + UA_AsyncServiceList asyncServiceCalls = client->asyncServiceCalls; + LIST_INIT(&client->asyncServiceCalls); + if(asyncServiceCalls.lh_first) + asyncServiceCalls.lh_first->pointers.le_prev = &asyncServiceCalls.lh_first; + + /* Cancel and remove the elements from the local list */ AsyncServiceCall *ac, *ac_tmp; - LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) { + LIST_FOREACH_SAFE(ac, &asyncServiceCalls, pointers, ac_tmp) { LIST_REMOVE(ac, pointers); UA_Client_AsyncService_cancel(client, ac, statusCode); UA_free(ac); @@ -627,17 +642,28 @@ UA_Client_removeCallback(UA_Client *client, UA_UInt64 callbackId) { static void asyncServiceTimeoutCheck(UA_Client *client) { + /* Make this function reentrant. One of the async callbacks could indirectly + * operate on the list. Moving all elements to a local list before iterating + * that. */ + UA_AsyncServiceList asyncServiceCalls; AsyncServiceCall *ac, *ac_tmp; UA_DateTime now = UA_DateTime_nowMonotonic(); + LIST_INIT(&asyncServiceCalls); LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) { if(!ac->timeout) continue; if(ac->start + (UA_DateTime)(ac->timeout * UA_DATETIME_MSEC) <= now) { LIST_REMOVE(ac, pointers); - UA_Client_AsyncService_cancel(client, ac, UA_STATUSCODE_BADTIMEOUT); - UA_free(ac); + LIST_INSERT_HEAD(&asyncServiceCalls, ac, pointers); } } + + /* Cancel and remove the elements from the local list */ + LIST_FOREACH_SAFE(ac, &asyncServiceCalls, pointers, ac_tmp) { + LIST_REMOVE(ac, pointers); + UA_Client_AsyncService_cancel(client, ac, UA_STATUSCODE_BADTIMEOUT); + UA_free(ac); + } } static void diff --git a/src/client/ua_client_connect.c b/src/client/ua_client_connect.c index 5048262be47..84e85b7cffc 100644 --- a/src/client/ua_client_connect.c +++ b/src/client/ua_client_connect.c @@ -396,13 +396,6 @@ processOPNResponse(UA_Client *client, const UA_ByteString *message) { return; } - /* Response.securityToken.revisedLifetime is UInt32 we need to cast it to - * DateTime=Int64 we take 75% of lifetime to start renewing as described in - * standard */ - client->nextChannelRenewal = UA_DateTime_nowMonotonic() - + (UA_DateTime) (response.securityToken.revisedLifetime - * (UA_Double) UA_DATETIME_MSEC * 0.75); - /* Move the nonce out of the response */ UA_ByteString_clear(&client->channel.remoteNonce); client->channel.remoteNonce = response.serverNonce; @@ -415,6 +408,28 @@ processOPNResponse(UA_Client *client, const UA_ByteString *message) { client->channel.securityToken = response.securityToken; client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT; + /* Log a warning if the SecurityToken is not "fresh". Use the normal system + * clock to do the comparison. */ + UA_DateTime wallClockNow = UA_DateTime_now(); + if(wallClockNow - client->channel.securityToken.createdAt >= UA_DATETIME_SEC * 10 || + wallClockNow - client->channel.securityToken.createdAt <= -UA_DATETIME_SEC * 10) + UA_LOG_WARNING_CHANNEL(&client->config.logger, &client->channel, "The \"CreatedAt\" " + "timestamp of the received ChannelSecurityToken does not match " + "with the local system clock"); + + /* The internal "monotonic" clock is used by the SecureChannel to validate + * that the SecurityToken is still valid. The monotonic clock is independent + * from the system clock getting changed or synchronized to a master clock + * during runtime. */ + client->channel.securityToken.createdAt = UA_DateTime_nowMonotonic(); + + /* Response.securityToken.revisedLifetime is UInt32, we need to cast it to + * DateTime=Int64. After 75% of the lifetime the renewal takes place as + * described in standard */ + client->nextChannelRenewal = client->channel.securityToken.createdAt + + (UA_DateTime) (response.securityToken.revisedLifetime * + (UA_Double) UA_DATETIME_MSEC * 0.75); + /* Compute the new local keys. The remote keys are updated when a message * with the new SecurityToken is received. */ retval = UA_SecureChannel_generateLocalKeys(&client->channel); diff --git a/src/client/ua_client_internal.h b/src/client/ua_client_internal.h index f4a58c777dc..96901a13008 100644 --- a/src/client/ua_client_internal.h +++ b/src/client/ua_client_internal.h @@ -95,6 +95,8 @@ void UA_Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac, UA_StatusCode statusCode); +typedef LIST_HEAD(UA_AsyncServiceList, AsyncServiceCall) UA_AsyncServiceList; + void UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode); @@ -147,7 +149,7 @@ struct UA_Client { UA_Boolean pendingConnectivityCheck; /* Async Service */ - LIST_HEAD(, AsyncServiceCall) asyncServiceCalls; + UA_AsyncServiceList asyncServiceCalls; /* Subscriptions */ #ifdef UA_ENABLE_SUBSCRIPTIONS diff --git a/src/pubsub/ua_pubsub_networkmessage_json.c b/src/pubsub/ua_pubsub_networkmessage_json.c index e73af226c75..45b696c0dc3 100644 --- a/src/pubsub/ua_pubsub_networkmessage_json.c +++ b/src/pubsub/ua_pubsub_networkmessage_json.c @@ -286,6 +286,8 @@ DataSetPayload_decodeJsonInternal(void* dsmP, const UA_DataType *type, } size_t length = (size_t)parseCtx->tokenArray[parseCtx->index].size; + if(length > UA_UINT16_MAX) + return UA_STATUSCODE_BADDECODINGERROR; UA_String *fieldNames = (UA_String*)UA_calloc(length, sizeof(UA_String)); dsm->data.keyFrameData.fieldNames = fieldNames; dsm->data.keyFrameData.fieldCount = (UA_UInt16)length; diff --git a/src/pubsub/ua_pubsub_security.c b/src/pubsub/ua_pubsub_security.c index 42690177e56..25139f8be68 100644 --- a/src/pubsub/ua_pubsub_security.c +++ b/src/pubsub/ua_pubsub_security.c @@ -84,6 +84,11 @@ verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer, if(doValidate) { size_t sigSize = securityPolicy->symmetricModule.cryptoModule. signatureAlgorithm.getLocalSignatureSize(channelContext); + if(buffer->length < sigSize) { + UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURITYPOLICY, + "PubSub receive. Message too short for signature"); + return UA_STATUSCODE_BADSECURITYCHECKSFAILED; + } UA_ByteString toBeVerified = {buffer->length - sigSize, buffer->data}; UA_ByteString signature = {sigSize, buffer->data + buffer->length - sigSize}; diff --git a/src/server/ua_server_discovery_mdns.c b/src/server/ua_server_discovery_mdns.c index fccb9c73145..ca39fe06bde 100644 --- a/src/server/ua_server_discovery_mdns.c +++ b/src/server/ua_server_discovery_mdns.c @@ -214,8 +214,10 @@ UA_DiscoveryManager_removeEntryFromServersOnNetwork(UA_Server *server, const cha /* Remove from list */ LIST_REMOVE(entry, pointers); UA_ServerOnNetwork_clear(&entry->serverOnNetwork); - if(entry->pathTmp) + if(entry->pathTmp) { UA_free(entry->pathTmp); + entry->pathTmp = NULL; + } UA_free(entry); return UA_STATUSCODE_GOOD; } @@ -223,12 +225,13 @@ UA_DiscoveryManager_removeEntryFromServersOnNetwork(UA_Server *server, const cha static void mdns_append_path_to_url(UA_String *url, const char *path) { size_t pathLen = strlen(path); + size_t newUrlLen = url->length + pathLen; //size of the new url string incl. the path /* todo: malloc may fail: return a statuscode */ char *newUrl = (char *)UA_malloc(url->length + pathLen); memcpy(newUrl, url->data, url->length); memcpy(newUrl + url->length, path, pathLen); UA_String_clear(url); - url->length = url->length + pathLen; + url->length = newUrlLen; url->data = (UA_Byte *) newUrl; } @@ -251,7 +254,7 @@ setTxt(UA_Server *server, const struct resource *r, UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Cannot alloc memory for mDNS srv path"); return; } - memcpy(&(entry->pathTmp), &path, pathLen); + memcpy(entry->pathTmp, path, pathLen); entry->pathTmp[pathLen] = '\0'; } } else { @@ -322,6 +325,7 @@ setSrv(UA_Server *server, const struct resource *r, if(entry->pathTmp) { mdns_append_path_to_url(&entry->serverOnNetwork.discoveryUrl, entry->pathTmp); UA_free(entry->pathTmp); + entry->pathTmp = NULL; } } diff --git a/src/server/ua_server_ns0_diagnostics.c b/src/server/ua_server_ns0_diagnostics.c index 72ac9aecb77..c35c1f4e95f 100644 --- a/src/server/ua_server_ns0_diagnostics.c +++ b/src/server/ua_server_ns0_diagnostics.c @@ -73,16 +73,22 @@ readSubscriptionDiagnostics(UA_Server *server, const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp, const UA_NumericRange *range, UA_DataValue *value) { + UA_LOCK(&server->serviceMutex); + /* Check the Subscription pointer */ UA_Subscription *sub = (UA_Subscription*)nodeContext; - if(!sub) + if(!sub) { + UA_UNLOCK(&server->serviceMutex); return UA_STATUSCODE_BADINTERNALERROR; + } /* Read the BrowseName */ UA_QualifiedName bn; UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn); - if(res != UA_STATUSCODE_GOOD) + if(res != UA_STATUSCODE_GOOD) { + UA_UNLOCK(&server->serviceMutex); return res; + } /* Set the value */ UA_SubscriptionDiagnosticsDataType sddt; @@ -112,17 +118,21 @@ readSubscriptionDiagnostics(UA_Server *server, UA_SubscriptionDiagnosticsDataType_clear(&sddt); UA_QualifiedName_clear(&bn); + + UA_UNLOCK(&server->serviceMutex); return res; } /* If the nodeContext == NULL, return all subscriptions in the server. * Otherwise only for the current session. */ -UA_StatusCode -readSubscriptionDiagnosticsArray(UA_Server *server, - const UA_NodeId *sessionId, void *sessionContext, - const UA_NodeId *nodeId, void *nodeContext, - UA_Boolean sourceTimestamp, - const UA_NumericRange *range, UA_DataValue *value) { +static UA_StatusCode +readSubscriptionDiagnosticsArrayLocked(UA_Server *server, + const UA_NodeId *sessionId, void *sessionContext, + const UA_NodeId *nodeId, void *nodeContext, + UA_Boolean sourceTimestamp, + const UA_NumericRange *range, UA_DataValue *value) { + UA_LOCK_ASSERT(&server->serviceMutex, 1); + /* Get the current session */ size_t sdSize = 0; UA_Session *session = NULL; @@ -168,6 +178,20 @@ readSubscriptionDiagnosticsArray(UA_Server *server, return UA_STATUSCODE_GOOD; } +UA_StatusCode +readSubscriptionDiagnosticsArray(UA_Server *server, + const UA_NodeId *sessionId, void *sessionContext, + const UA_NodeId *nodeId, void *nodeContext, + UA_Boolean sourceTimestamp, + const UA_NumericRange *range, UA_DataValue *value) { + UA_LOCK(&server->serviceMutex); + UA_StatusCode res = readSubscriptionDiagnosticsArrayLocked( + server, sessionId, sessionContext, nodeId, nodeContext, + sourceTimestamp, range, value); + UA_UNLOCK(&server->serviceMutex); + return res; +} + void createSubscriptionObject(UA_Server *server, UA_Session *session, UA_Subscription *sub) { @@ -328,16 +352,22 @@ readSessionDiagnostics(UA_Server *server, const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp, const UA_NumericRange *range, UA_DataValue *value) { + UA_LOCK(&server->serviceMutex); + /* Get the Session */ UA_Session *session = UA_Server_getSessionById(server, sessionId); - if(!session) + if(!session) { + UA_UNLOCK(&server->serviceMutex); return UA_STATUSCODE_BADINTERNALERROR; + } /* Read the BrowseName */ UA_QualifiedName bn; UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn); - if(res != UA_STATUSCODE_GOOD) + if(res != UA_STATUSCODE_GOOD) { + UA_UNLOCK(&server->serviceMutex); return res; + } union { UA_SessionDiagnosticsDataType sddt; @@ -356,9 +386,9 @@ readSessionDiagnostics(UA_Server *server, /* Reuse the datasource callback. Forward a non-null nodeContext to * indicate that we want to see only the subscriptions for the current * session. */ - res = readSubscriptionDiagnosticsArray(server, sessionId, sessionContext, - nodeId, (void*)0x01, - sourceTimestamp, range, value); + res = readSubscriptionDiagnosticsArrayLocked(server, sessionId, sessionContext, + nodeId, (void*)0x01, + sourceTimestamp, range, value); goto cleanup; } else if(equalBrowseName(&bn.name, "SessionDiagnostics")) { setSessionDiagnostics(session, &data.sddt); @@ -399,7 +429,7 @@ readSessionDiagnostics(UA_Server *server, res = UA_Variant_setScalarCopy(&value->value, content, type); } else { size_t len = *(size_t*)content; - content = (void*)(((uintptr_t)content) + sizeof(size_t)); + content = *(void**)((uintptr_t)content + sizeof(size_t)); res = UA_Variant_setArrayCopy(&value->value, content, len, type); } if(UA_LIKELY(res == UA_STATUSCODE_GOOD)) @@ -412,6 +442,7 @@ readSessionDiagnostics(UA_Server *server, cleanup: UA_QualifiedName_clear(&bn); + UA_UNLOCK(&server->serviceMutex); return res; } diff --git a/src/server/ua_services_attribute.c b/src/server/ua_services_attribute.c index 2cf5f459964..5c9f5d08349 100644 --- a/src/server/ua_services_attribute.c +++ b/src/server/ua_services_attribute.c @@ -1833,6 +1833,14 @@ Service_HistoryRead(UA_Server *server, UA_Session *session, return; } + /* Check if the configured History-Backend supports the requested history type */ + if(!readHistory) { + UA_LOG_INFO_SESSION(&server->config.logger, session, + "The configured HistoryBackend does not support the selected history-type."); + response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED; + return; + } + /* Something to do? */ if(request->nodesToReadSize == 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO; diff --git a/src/server/ua_services_method.c b/src/server/ua_services_method.c index 3418e5855de..6381df7a314 100644 --- a/src/server/ua_services_method.c +++ b/src/server/ua_services_method.c @@ -350,6 +350,28 @@ Operation_CallMethodAsync(UA_Server *server, UA_Session *session, UA_UInt32 requ goto cleanup; } + /* Check the NodeClass */ + if(method->head.nodeClass != UA_NODECLASS_METHOD || + object->head.nodeClass != UA_NODECLASS_OBJECT) { + opResult->statusCode = UA_STATUSCODE_BADNODECLASSINVALID; + goto cleanup; + } + + /* Check the access rights */ + UA_Boolean executable = method->methodNode.executable; + if(session != &server->adminSession) { + executable = executable && server->config.accessControl. + getUserExecutableOnObject(server, &server->config.accessControl, + &session->sessionId, session->sessionHandle, + &opRequest->methodId, method->head.context, + &opRequest->objectId, object->head.context); + } + + if(!executable) { + opResult->statusCode = UA_STATUSCODE_BADNOTEXECUTABLE; + goto cleanup; + } + /* <-- Async method call --> */ /* No AsyncResponse allocated so far */ diff --git a/src/server/ua_services_session.c b/src/server/ua_services_session.c index 0a940ea5a9b..3626efd44cd 100644 --- a/src/server/ua_services_session.c +++ b/src/server/ua_services_session.c @@ -781,7 +781,7 @@ Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel, /* Check the user token signature */ response->responseHeader.serviceResult = - checkSignature(server, channel->securityPolicy, tempChannelContext, + checkSignature(server, securityPolicy, tempChannelContext, &session->serverNonce, &request->userTokenSignature); /* Delete the temporary channel context */ diff --git a/src/server/ua_services_subscription.c b/src/server/ua_services_subscription.c index cb485c7705b..9ec6b40523b 100644 --- a/src/server/ua_services_subscription.c +++ b/src/server/ua_services_subscription.c @@ -482,12 +482,19 @@ Operation_TransferSubscription(UA_Server *server, UA_Session *session, } /* Check with AccessControl if the transfer is allowed */ - if(!server->config.accessControl.allowTransferSubscription || - !server->config.accessControl. - allowTransferSubscription(server, &server->config.accessControl, - oldSession ? &oldSession->sessionId : NULL, - oldSession ? oldSession->sessionHandle : NULL, - &session->sessionId, session->sessionHandle)) { + UA_Boolean transferAllowed = + (server->config.accessControl.allowTransferSubscription != NULL); + if(transferAllowed) { + UA_UNLOCK(&server->serviceMutex); + transferAllowed = server->config.accessControl. + allowTransferSubscription(server, &server->config.accessControl, + oldSession ? &oldSession->sessionId : NULL, + oldSession ? oldSession->sessionHandle : NULL, + &session->sessionId, session->sessionHandle); + UA_LOCK(&server->serviceMutex); + } + + if(!transferAllowed) { result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; return; } @@ -542,6 +549,15 @@ Operation_TransferSubscription(UA_Server *server, UA_Session *session, } sub->monitoredItemsSize = 0; + /* Move over the samplingMonitoredItems and adjust the backpointers */ + LIST_INIT(&newSub->samplingMonitoredItems); + UA_MonitoredItem *smon, *smon_tmp; + LIST_FOREACH_SAFE(smon, &sub->samplingMonitoredItems, sampling.samplingListEntry, smon_tmp) { + LIST_REMOVE(smon, sampling.samplingListEntry); + LIST_INSERT_HEAD(&newSub->samplingMonitoredItems, smon, + sampling.samplingListEntry); + } + /* Move over the notification queue */ TAILQ_INIT(&newSub->notificationQueue); UA_Notification *nn, *nn_tmp; diff --git a/src/server/ua_services_view.c b/src/server/ua_services_view.c index c8f632588a1..002a46c09c7 100644 --- a/src/server/ua_services_view.c +++ b/src/server/ua_services_view.c @@ -675,14 +675,17 @@ browseWithContinuation(UA_Server *server, UA_Session *session, return true; } - if(session != &server->adminSession && - !server->config.accessControl. - allowBrowseNode(server, &server->config.accessControl, - &session->sessionId, session->sessionHandle, - &descr->nodeId, node->head.context)) { - result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; - UA_NODESTORE_RELEASE(server, node); - return true; + if(session != &server->adminSession) { + UA_UNLOCK(&server->serviceMutex); + UA_Boolean allowed = server->config.accessControl.allowBrowseNode( + server, &server->config.accessControl, &session->sessionId, + session->sessionHandle, &descr->nodeId, node->head.context); + UA_LOCK(&server->serviceMutex); + if(!allowed) { + result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; + UA_NODESTORE_RELEASE(server, node); + return true; + } } RefResult rr; @@ -996,6 +999,25 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session, if(!node) continue; + /* Check whether the session is allowed to browse this node. + * Mirrors the access-control gate applied in browseWithContinuation(). + * Without this check, a client denied direct Browse on a node can + * still use it as a waypoint in TranslateBrowsePathsToNodeIds, + * disclosing hidden intermediate nodes and their children. */ + if(session != &server->adminSession) { + UA_UNLOCK(&server->serviceMutex); + UA_Boolean canBrowse = + server->config.accessControl.allowBrowseNode( + server, &server->config.accessControl, + &session->sessionId, session->sessionHandle, + ¤t->targets[i].nodeId, node->head.context); + UA_LOCK(&server->serviceMutex); + if(!canBrowse) { + UA_NODESTORE_RELEASE(server, node); + continue; + } + } + /* Test whether the node fits the class mask */ UA_Boolean skip = !matchClassMask(node, nodeClassMask); @@ -1146,6 +1168,25 @@ Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session, const UA_Node *node = UA_NODESTORE_GET(server, &next->targets[k].nodeId); if(!node) continue; + + /* Check whether the session is allowed to browse the resolved target. + * Without this check, a client denied direct Browse on a terminal node + * can still have its NodeId disclosed as the result of path + * translation. */ + if(session != &server->adminSession) { + UA_UNLOCK(&server->serviceMutex); + UA_Boolean canBrowse = + server->config.accessControl.allowBrowseNode( + server, &server->config.accessControl, + &session->sessionId, session->sessionHandle, + &next->targets[k].nodeId, node->head.context); + UA_LOCK(&server->serviceMutex); + if(!canBrowse) { + UA_NODESTORE_RELEASE(server, node); + continue; + } + } + UA_Boolean match = UA_QualifiedName_equal(browseNameFilter, &node->head.browseName); UA_NODESTORE_RELEASE(server, node); if(!match) diff --git a/src/server/ua_subscription_datachange.c b/src/server/ua_subscription_datachange.c index 5fb1fe6dbb4..677b7d6de80 100644 --- a/src/server/ua_subscription_datachange.c +++ b/src/server/ua_subscription_datachange.c @@ -54,13 +54,20 @@ detectScalarDeadBand(const void *data1, const void *data2, static UA_Boolean detectVariantDeadband(const UA_Variant *value, const UA_Variant *oldValue, const UA_Double deadbandValue) { + /* Be careful to avoid a NULL access. We could have the value a scalar and + * oldValue an empty array. Both define a type and arrayLength == 0. */ if(value->arrayLength != oldValue->arrayLength) return true; if(value->type != oldValue->type) return true; + if(UA_Variant_isScalar(value) != UA_Variant_isScalar(oldValue)) + return true; + + /* Treat scalars as an array of length 1 and iterate */ size_t length = 1; if(!UA_Variant_isScalar(value)) length = value->arrayLength; + uintptr_t data = (uintptr_t)value->data; uintptr_t oldData = (uintptr_t)oldValue->data; UA_UInt32 memSize = value->type->memSize; @@ -103,6 +110,10 @@ detectValueChange(UA_Server *server, UA_MonitoredItem *mon, UA_assert(trigger == UA_DATACHANGETRIGGER_STATUSVALUE || trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP); + /* Can we compare values? */ + if(value->hasValue != mon->lastValue.hasValue) + return true; + /* Test absolute deadband */ if(dcf && dcf->deadbandType == UA_DEADBANDTYPE_ABSOLUTE && value->value.type != NULL && UA_DataType_isNumeric(value->value.type)) @@ -119,8 +130,6 @@ detectValueChange(UA_Server *server, UA_MonitoredItem *mon, } /* Has the value changed? */ - if(value->hasValue != mon->lastValue.hasValue) - return true; return (UA_order(&value->value, &mon->lastValue.value, &UA_TYPES[UA_TYPES_VARIANT]) != UA_ORDER_EQ); } diff --git a/src/ua_securechannel.c b/src/ua_securechannel.c index f62aaf58fcb..6cef858ebc1 100644 --- a/src/ua_securechannel.c +++ b/src/ua_securechannel.c @@ -102,6 +102,22 @@ void UA_SecureChannel_close(UA_SecureChannel *channel) { /* Set the status to closed */ channel->state = UA_SECURECHANNELSTATE_CLOSED; + channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL; + + /* Reset the SecurityMode and config */ + channel->securityMode = UA_MESSAGESECURITYMODE_INVALID; + memset(&channel->config, 0, sizeof(UA_ConnectionConfig)); + + /* Clean up the SecurityToken */ + UA_ChannelSecurityToken_clear(&channel->securityToken); + UA_ChannelSecurityToken_clear(&channel->altSecurityToken); + + /* Delete the channel context for the security policy */ + if(channel->securityPolicy) { + channel->securityPolicy->channelModule.deleteContext(channel->channelContext); + channel->securityPolicy = NULL; + channel->channelContext = NULL; + } /* Detach from the connection and close the connection */ if(channel->connection) { @@ -110,6 +126,15 @@ UA_SecureChannel_close(UA_SecureChannel *channel) { UA_Connection_detachSecureChannel(channel->connection); } + /* Clean up certificate and nonces */ + UA_ByteString_clear(&channel->remoteCertificate); + UA_ByteString_clear(&channel->localNonce); + UA_ByteString_clear(&channel->remoteNonce); + + /* Reset the sequence numbers */ + channel->receiveSequenceNumber = 0; + channel->sendSequenceNumber = 0; + /* Detach Sessions from the SecureChannel. This also removes outstanding * Publish requests whose RequestId is valid only for the SecureChannel. */ UA_SessionHeader *sh; @@ -122,19 +147,7 @@ UA_SecureChannel_close(UA_SecureChannel *channel) { } } - /* Delete the channel context for the security policy */ - if(channel->securityPolicy) { - channel->securityPolicy->channelModule.deleteContext(channel->channelContext); - channel->securityPolicy = NULL; - channel->channelContext = NULL; - } - - /* Delete members */ - UA_ByteString_clear(&channel->remoteCertificate); - UA_ByteString_clear(&channel->localNonce); - UA_ByteString_clear(&channel->remoteNonce); - UA_ChannelSecurityToken_clear(&channel->securityToken); - UA_ChannelSecurityToken_clear(&channel->altSecurityToken); + /* Delete remaining chunks */ UA_SecureChannel_deleteBuffered(channel); } diff --git a/src/ua_types.c b/src/ua_types.c index 7e8f7c43d88..bedde73e5b0 100644 --- a/src/ua_types.c +++ b/src/ua_types.c @@ -636,8 +636,11 @@ checkAdjustRange(const UA_Variant *v, UA_NumericRange *range) { /* Check that the number of elements in the variant matches the array * dimensions */ size_t elements = 1; - for(size_t i = 0; i < dims_count; ++i) + for(size_t i = 0; i < dims_count; ++i) { + if(dims[i] != 0 && elements > SIZE_MAX / dims[i]) + return UA_STATUSCODE_BADINTERNALERROR; elements *= dims[i]; + } if(elements != v->arrayLength) return UA_STATUSCODE_BADINTERNALERROR; @@ -700,6 +703,11 @@ computeStrides(const UA_Variant *v, const UA_NumericRange range, *block = running_dimssize * dimrange; *stride = running_dimssize * dims[k]; } + /* Overflow in running_dimssize is only possible when the Variant has + * passed a corrupted state through checkAdjustRange. Guard here as a + * defence-in-depth measure. */ + if(running_dimssize != 0 && dims[k] > SIZE_MAX / running_dimssize) + break; *first += running_dimssize * range.dimensions[k].min; running_dimssize *= dims[k]; } @@ -931,7 +939,7 @@ Variant_setRange(UA_Variant *v, void *array, size_t arraySize, /* If members were moved, initialize original array to prevent reuse */ if(!copy && !v->type->pointerFree) - memset(array, 0, sizeof(elem_size)*arraySize); + memset(array, 0, elem_size*arraySize); return retval; } @@ -1436,7 +1444,7 @@ extensionObjectOrder(const UA_ExtensionObject *p1, const UA_ExtensionObject *p2, case UA_EXTENSIONOBJECT_DECODED: default: { const UA_DataType *type1 = p1->content.decoded.type; - const UA_DataType *type2 = p1->content.decoded.type; + const UA_DataType *type2 = p2->content.decoded.type; if(type1 != type2) return ((uintptr_t)type1 < (uintptr_t)type2) ? UA_ORDER_LESS : UA_ORDER_MORE; if(!type1) @@ -1752,7 +1760,9 @@ UA_Array_copy(const void *src, size_t size, return UA_STATUSCODE_GOOD; } - if(!type) + /* Check the array consistency -- defensive programming in case the user + * manually created an inconsistent array */ + if(UA_UNLIKELY(!type || !src)) return UA_STATUSCODE_BADINTERNALERROR; /* calloc, so we don't have to check retval in every iteration of copying */ @@ -1848,7 +1858,7 @@ UA_Array_append(void **p, size_t *size, void *newElem, return UA_STATUSCODE_GOOD; } -UA_StatusCode UA_EXPORT +UA_StatusCode UA_Array_appendCopy(void **p, size_t *size, const void *newElem, const UA_DataType *type) { char scratch[512]; diff --git a/src/ua_types_encoding_binary.c b/src/ua_types_encoding_binary.c index 7b3a4f6b84e..3f03c2966e6 100644 --- a/src/ua_types_encoding_binary.c +++ b/src/ua_types_encoding_binary.c @@ -281,16 +281,14 @@ DECODE_BINARY(UInt64) { /************************/ /* Can we reuse the integer encoding mechanism by casting floating point - * values? */ -#if (UA_FLOAT_IEEE754 == 1) && (UA_LITTLE_ENDIAN == UA_FLOAT_LITTLE_ENDIAN) -# define Float_encodeBinary UInt32_encodeBinary -# define Float_decodeBinary UInt32_decodeBinary -# define Double_encodeBinary UInt64_encodeBinary -# define Double_decodeBinary UInt64_decodeBinary -#else + * values? For single float values we ensure that only quiet NAN are used. + * For float arrays we want to have the speed advantage of just memcpy (if + * the processor architecture uses IEE754). We get array-memcpy by the + * "overlayable" bit in the datatype description. */ +#if (UA_FLOAT_IEEE754 < 1) || (UA_LITTLE_ENDIAN != UA_FLOAT_LITTLE_ENDIAN) #include - +#define UA_SLOW_IEEE754 1 #pragma message "No native IEEE 754 format detected. Use slow generic encoding." /* Handling of IEEE754 floating point values was taken from Beej's Guide to @@ -326,6 +324,8 @@ unpack754(uint64_t i, unsigned bits, unsigned expbits) { return result; } +#endif + /* Float */ #define FLOAT_NAN 0xffc00000 #define FLOAT_INF 0x7f800000 @@ -335,19 +335,26 @@ unpack754(uint64_t i, unsigned bits, unsigned expbits) { ENCODE_BINARY(Float) { UA_Float f = *src; u32 encoded; - /* cppcheck-suppress duplicateExpression */ - if(f != f) encoded = FLOAT_NAN; + if(UA_UNLIKELY(f != f)) encoded = FLOAT_NAN; /* quit NAN */ +#ifndef UA_SLOW_IEEE754 + else memcpy(&encoded, &f, sizeof(UA_Float)); +#else else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0; else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF; else encoded = (u32)pack754(f, 32, 8); +#endif return ENCODE_DIRECT(&encoded, UInt32); } DECODE_BINARY(Float) { u32 decoded; status ret = DECODE_DIRECT(&decoded, UInt32); - if(ret != UA_STATUSCODE_GOOD) - return ret; + UA_CHECK_STATUS(ret, return ret); +#ifndef UA_SLOW_IEEE754 + if(UA_UNLIKELY((decoded >= 0x7f800001 && decoded <= 0x7fffffff) || + (decoded >= 0xff800001))) decoded = FLOAT_NAN; + memcpy(dst, &decoded, sizeof(UA_Float)); +#else if(decoded == 0) *dst = 0.0f; else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f; else if(decoded == FLOAT_INF) *dst = INFINITY; @@ -355,6 +362,7 @@ DECODE_BINARY(Float) { else if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) || (decoded >= 0xff800001)) *dst = NAN; else *dst = (UA_Float)unpack754(decoded, 32, 8); +#endif return UA_STATUSCODE_GOOD; } @@ -368,10 +376,14 @@ ENCODE_BINARY(Double) { UA_Double d = *src; u64 encoded; /* cppcheck-suppress duplicateExpression */ - if(d != d) encoded = DOUBLE_NAN; + if(UA_UNLIKELY(d != d)) encoded = DOUBLE_NAN; /* quiet NAN*/ +#ifndef UA_SLOW_IEEE754 + else memcpy(&encoded, &d, sizeof(UA_Double)); +#else else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0; else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF; else encoded = pack754(d, 64, 11); + #endif return ENCODE_DIRECT(&encoded, UInt64); } @@ -379,6 +391,11 @@ DECODE_BINARY(Double) { u64 decoded; status ret = DECODE_DIRECT(&decoded, UInt64); UA_CHECK_STATUS(ret, return ret); +#ifndef UA_SLOW_IEEE754 + if(UA_UNLIKELY((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) || + (decoded >= 0xfff0000000000001L))) decoded = DOUBLE_NAN; + memcpy(dst, &decoded, sizeof(UA_Double)); +#else if(decoded == 0) *dst = 0.0; else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0; else if(decoded == DOUBLE_INF) *dst = INFINITY; @@ -386,11 +403,10 @@ DECODE_BINARY(Double) { else if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) || (decoded >= 0xfff0000000000001L)) *dst = NAN; else *dst = (UA_Double)unpack754(decoded, 64, 11); +#endif return UA_STATUSCODE_GOOD; } -#endif - /******************/ /* Array Handling */ /******************/ @@ -481,7 +497,8 @@ Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length, * sizeof(UA_DataValue) == 80 and an empty DataValue is encoded with just * one byte. We use 128 as the smallest power of 2 larger than 80. */ size_t length = (size_t)signed_length; - UA_CHECK(ctx->pos + ((type->memSize * length) / 128) <= ctx->end, + size_t remaining = (size_t)(ctx->end - ctx->pos); + UA_CHECK(length / 128 <= remaining / type->memSize, return UA_STATUSCODE_BADDECODINGERROR); /* Allocate memory */ @@ -983,8 +1000,17 @@ ENCODE_BINARY(Variant) { const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0; if(isArray) { encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY; - if(hasDimensions) + if(hasDimensions) { encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS; + size_t totalRequiredSize = 1; + for(size_t i = 0; i < src->arrayDimensionsSize; ++i) { + if(src->arrayDimensions[i] != 0 && + totalRequiredSize > SIZE_MAX / src->arrayDimensions[i]) + return UA_STATUSCODE_BADENCODINGERROR; + totalRequiredSize *= src->arrayDimensions[i]; + } + if(totalRequiredSize != src->arrayLength) return UA_STATUSCODE_BADENCODINGERROR; + } } /* Encode the encoding byte */ @@ -1093,9 +1119,22 @@ DECODE_BINARY(Variant) { } /* Decode array dimensions */ - if(isArray && (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0) + if(isArray && (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0) { ret |= Array_decodeBinary((void**)&dst->arrayDimensions, &dst->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32], ctx); + /* Validate array length against array dimensions */ + size_t totalSize = 1; + for(size_t i = 0; i < dst->arrayDimensionsSize; ++i) { + if(dst->arrayDimensions[i] == 0) { + ret = UA_STATUSCODE_BADDECODINGERROR; + } else if(totalSize > SIZE_MAX / dst->arrayDimensions[i]) { + ret = UA_STATUSCODE_BADDECODINGERROR; + } else { + totalSize *= dst->arrayDimensions[i]; + } + } + UA_CHECK(totalSize == dst->arrayLength, ret = UA_STATUSCODE_BADDECODINGERROR); + } ctx->depth--; return ret; @@ -1199,10 +1238,10 @@ ENCODE_BINARY(DiagnosticInfo) { ret |= ENCODE_DIRECT(&src->symbolicId, UInt32); /* Int32 */ if(src->hasNamespaceUri) ret |= ENCODE_DIRECT(&src->namespaceUri, UInt32); /* Int32 */ - if(src->hasLocalizedText) - ret |= ENCODE_DIRECT(&src->localizedText, UInt32); /* Int32 */ if(src->hasLocale) ret |= ENCODE_DIRECT(&src->locale, UInt32); /* Int32 */ + if(src->hasLocalizedText) + ret |= ENCODE_DIRECT(&src->localizedText, UInt32); /* Int32 */ if(ret != UA_STATUSCODE_GOOD) return ret; @@ -1245,14 +1284,14 @@ DECODE_BINARY(DiagnosticInfo) { dst->hasNamespaceUri = true; ret |= DECODE_DIRECT(&dst->namespaceUri, UInt32); /* Int32 */ } - if(encodingMask & 0x04u) { - dst->hasLocalizedText = true; - ret |= DECODE_DIRECT(&dst->localizedText, UInt32); /* Int32 */ - } if(encodingMask & 0x08u) { dst->hasLocale = true; ret |= DECODE_DIRECT(&dst->locale, UInt32); /* Int32 */ } + if(encodingMask & 0x04u) { + dst->hasLocalizedText = true; + ret |= DECODE_DIRECT(&dst->localizedText, UInt32); /* Int32 */ + } if(encodingMask & 0x10u) { dst->hasAdditionalInfo = true; ret |= DECODE_DIRECT(&dst->additionalInfo, String); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 89c23af6b0d..4e9cf9c9aca 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -585,6 +585,10 @@ if(UA_ENABLE_ENCRYPTION) add_executable(check_client_encryption client/check_client_encryption.c $ $) target_link_libraries(check_client_encryption ${LIBS}) add_test_valgrind(client_encryption ${TESTS_BINARY_DIR}/check_client_encryption) + + add_executable(check_crl_validation encryption/check_crl_validation.c $ $) + target_link_libraries(check_crl_validation ${LIBS}) + add_test_valgrind(crl_validation ${TESTS_BINARY_DIR}/check_crl_validation) endif() if(UA_ENABLE_ENCRYPTION_MBEDTLS) diff --git a/tests/check_types_builtin.c b/tests/check_types_builtin.c index ef124812bb5..a365cc1266c 100644 --- a/tests/check_types_builtin.c +++ b/tests/check_types_builtin.c @@ -809,10 +809,6 @@ START_TEST(UA_Float_encodeShallWorkOnExample) { {0x00, 0x00, 0x80, 0x7F}, // INF {0x00, 0x00, 0x80, 0xFF} // -INF }; -#if defined(_MSC_VER) - /* On Visual Studio, -NAN is encoded differently */ - result[4][3] = 127; -#endif UA_Byte data[] = {0x55, 0x55, 0x55, 0x55}; UA_ByteString dst = {4, data}; diff --git a/tests/check_types_builtin_json.c b/tests/check_types_builtin_json.c index b3f4887f50f..bdc5137776a 100644 --- a/tests/check_types_builtin_json.c +++ b/tests/check_types_builtin_json.c @@ -4384,7 +4384,7 @@ START_TEST(UA_ByteString_bad_json_decode) { UA_StatusCode retval = UA_decodeJsonInternal(&buf, &out, &UA_TYPES[UA_TYPES_BYTESTRING]); // then - ck_assert_int_eq(retval, UA_STATUSCODE_GOOD); + ck_assert_int_ne(retval, UA_STATUSCODE_GOOD); UA_ByteString_clear(&out); } END_TEST diff --git a/tests/client/check_client.c b/tests/client/check_client.c index 22b02cdc8d3..4c083a5340d 100644 --- a/tests/client/check_client.c +++ b/tests/client/check_client.c @@ -180,7 +180,7 @@ START_TEST(Client_renewSecureChannel) { UA_fakeSleep((UA_UInt32)((UA_Double)cc->secureChannelLifeTime * 0.8)); /* Make the client renew the channel */ - retval = UA_Client_run_iterate(client, 0); + retval = UA_Client_run_iterate(client, 1); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); /* Now read */ @@ -224,7 +224,7 @@ START_TEST(Client_renewSecureChannelWithActiveSubscription) { for(int i = 0; i < 15; ++i) { UA_fakeSleep(1000); UA_Server_run_iterate(server, true); - retval = UA_Client_run_iterate(client, 0); + retval = UA_Client_run_iterate(client, 1); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); } diff --git a/tests/client/check_client_async_connect.c b/tests/client/check_client_async_connect.c index 8c86a51d36e..2a5d2472baa 100644 --- a/tests/client/check_client_async_connect.c +++ b/tests/client/check_client_async_connect.c @@ -77,6 +77,8 @@ START_TEST(Client_connect_async) { UA_Client_sendAsyncBrowseRequest(client, &bReq, asyncBrowseCallback, &asyncCounter, &reqId); } + /* Give network a chance to process packet */ + UA_realSleep(100); /* Manual clock for unit tests */ UA_Server_run_iterate(server, false); retval = UA_Client_run_iterate(client, 0); @@ -88,8 +90,8 @@ START_TEST(Client_connect_async) { UA_BrowseRequest_clear(&bReq); ck_assert_uint_eq(connected, true); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); - /* With default setting the client uses 7 iterations to connect */ - ck_assert_uint_eq(asyncCounter, 10-7); + /* With default setting the client uses 7 or 8 iterations to connect */ + ck_assert(asyncCounter == 10-7 || asyncCounter == 10-8); UA_Client_disconnectAsync(client); while(connected) { UA_Server_run_iterate(server, false); @@ -147,7 +149,7 @@ START_TEST(Client_no_connection) { //simulating unconnected server UA_Client_recvTesting_result = UA_STATUSCODE_BADCONNECTIONCLOSED; UA_Server_run_iterate(server, false); - retval = UA_Client_run_iterate(client, 0); /* Open connection */ + retval = UA_Client_run_iterate(client, 1); /* Open connection */ UA_Server_run_iterate(server, false); retval |= UA_Client_run_iterate(client, 0); /* Send HEL */ UA_Server_run_iterate(server, false); @@ -182,7 +184,7 @@ START_TEST(Client_run_iterate) { UA_Server_run_iterate(server, false); retval = UA_Client_run_iterate(client, 0); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); - sleep(0); + UA_realSleep(100); } UA_Client_delete(client); } diff --git a/tests/client/check_client_securechannel.c b/tests/client/check_client_securechannel.c index a536912f507..f6bd96955e7 100644 --- a/tests/client/check_client_securechannel.c +++ b/tests/client/check_client_securechannel.c @@ -160,7 +160,7 @@ START_TEST(SecureChannel_networkfail) { UA_Variant_init(&val); UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE); retval = UA_Client_readValueAttribute(client, nodeId, &val); - ck_assert(retval == UA_STATUSCODE_BADCONNECTIONCLOSED); + ck_assert(retval == UA_STATUSCODE_BADSECURECHANNELCLOSED); UA_Client_disconnect(client); UA_Client_delete(client); @@ -205,7 +205,7 @@ START_TEST(SecureChannel_cableunplugged) { client->connection.recv = UA_Client_recvTesting; /* Simulate network cable unplugged (no response from server) */ - UA_Client_recvTesting_result = UA_STATUSCODE_BADINTERNALERROR; + UA_Client_recvTesting_result = UA_STATUSCODE_BADCONNECTIONCLOSED; UA_Variant_init(&val); retval = UA_Client_readValueAttribute(client, nodeId, &val); diff --git a/tests/client/check_client_subscriptions.c b/tests/client/check_client_subscriptions.c index 6eb101e41d5..8c81e39adce 100644 --- a/tests/client/check_client_subscriptions.c +++ b/tests/client/check_client_subscriptions.c @@ -209,7 +209,7 @@ START_TEST(Client_subscription_async) { ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Server_run_iterate(server, true); - UA_Client_run_iterate(client, 0); + UA_Client_run_iterate(client, 1); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); UA_UInt32 subId = response.subscriptionId; diff --git a/tests/encryption/certificates.h b/tests/encryption/certificates.h index a3810e9deb8..75089746058 100644 --- a/tests/encryption/certificates.h +++ b/tests/encryption/certificates.h @@ -7,146 +7,146 @@ _UA_BEGIN_DECLS #define KEY_DER_LENGTH 1193 UA_Byte KEY_DER_DATA[1193] = { - 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe0, 0xc9, 0x91, 0x62, - 0xcd, 0x91, 0x68, 0x75, 0x2c, 0x32, 0x7a, 0xdd, 0xf1, 0xd6, 0x64, 0x77, 0x8b, 0x72, 0x9e, 0x14, - 0x2a, 0x62, 0x08, 0xd1, 0x89, 0x7d, 0xe2, 0x17, 0xdc, 0xb3, 0xda, 0xbc, 0x3a, 0x9f, 0x84, 0x03, - 0xd3, 0x2e, 0x68, 0xbe, 0xc1, 0x57, 0xcb, 0x2a, 0xe2, 0xd6, 0xcf, 0xc4, 0x7f, 0xbd, 0x53, 0x3f, - 0xeb, 0x39, 0x98, 0x69, 0xb0, 0x40, 0x14, 0xbf, 0xf5, 0x5a, 0x23, 0x23, 0xf4, 0x4c, 0xf8, 0xf1, - 0x03, 0x56, 0x6d, 0x7d, 0x1b, 0x93, 0xd7, 0x0f, 0xc1, 0x8c, 0x70, 0xe0, 0x2c, 0x55, 0x7e, 0xa1, - 0xfc, 0x05, 0xe9, 0xd7, 0xea, 0xb1, 0x5c, 0x0f, 0x9b, 0xac, 0x6a, 0x2e, 0xb4, 0xc5, 0xbf, 0x41, - 0x8f, 0xda, 0xfc, 0x85, 0xc6, 0xaa, 0x25, 0xe4, 0xb9, 0x9a, 0xc6, 0xd8, 0x9a, 0x31, 0x8a, 0x17, - 0x8b, 0x8c, 0x4e, 0x20, 0xd9, 0x71, 0xfc, 0x66, 0x3a, 0xfd, 0x49, 0x95, 0x54, 0xa8, 0xaf, 0x42, - 0x5e, 0xba, 0x26, 0xe6, 0xd3, 0xa0, 0xd2, 0x02, 0x3b, 0x51, 0x8b, 0x39, 0xd3, 0x97, 0xd2, 0xe4, - 0xd1, 0x01, 0x65, 0xab, 0x8e, 0xa2, 0x80, 0x5b, 0x5e, 0xbb, 0x11, 0x7f, 0x50, 0x1b, 0x2b, 0x0d, - 0x20, 0x40, 0xb5, 0xbf, 0xd1, 0x32, 0xfa, 0x25, 0xe1, 0x0d, 0x75, 0xfc, 0x11, 0xcf, 0x21, 0xdd, - 0x45, 0x16, 0xe4, 0x56, 0x58, 0x49, 0x33, 0xca, 0xaf, 0xe3, 0x17, 0x7b, 0x7a, 0x8f, 0xb1, 0xec, - 0x1c, 0x4d, 0xa2, 0xc2, 0xce, 0x8b, 0x19, 0x4b, 0xc0, 0xc4, 0x36, 0x6a, 0x7c, 0x5b, 0x89, 0x14, - 0x98, 0xcb, 0xa9, 0xca, 0x66, 0xf2, 0xaa, 0xf9, 0x12, 0x40, 0x0e, 0x6a, 0x78, 0x4d, 0x1f, 0x54, - 0x3c, 0x03, 0x7a, 0x91, 0xf5, 0xb7, 0x3d, 0xe2, 0xfc, 0x65, 0xb7, 0xaa, 0xa9, 0x39, 0x68, 0xa7, - 0xdb, 0x29, 0xc1, 0x40, 0x0b, 0x4e, 0xfb, 0xce, 0x74, 0xa5, 0x46, 0xb9, 0x02, 0x03, 0x01, 0x00, - 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb4, 0xc8, 0x07, 0x60, 0x01, 0xd9, 0xb6, 0xbb, 0xbd, 0x8e, - 0xdf, 0x97, 0xcd, 0xde, 0x51, 0xb0, 0x7e, 0xfa, 0xf0, 0x3d, 0x61, 0x94, 0xb4, 0x68, 0xe8, 0x7d, - 0xd0, 0x2e, 0xc6, 0xb5, 0xf2, 0xed, 0xbc, 0xeb, 0xfb, 0x3d, 0x24, 0x43, 0x47, 0xc4, 0x5a, 0x34, - 0x64, 0x56, 0x1a, 0x57, 0x0e, 0x83, 0x87, 0x04, 0x59, 0x86, 0xa7, 0x84, 0x0b, 0x9a, 0xbc, 0x3f, - 0xdd, 0x30, 0x40, 0x7f, 0x7c, 0x91, 0x76, 0xf1, 0xcc, 0xa7, 0xf0, 0xba, 0x3a, 0x96, 0x0a, 0x6e, - 0xcc, 0xe0, 0x84, 0x15, 0x91, 0xd6, 0x08, 0x71, 0xbd, 0xc5, 0x42, 0xad, 0xf2, 0xd2, 0x4e, 0x92, - 0xd3, 0x6a, 0x4e, 0x15, 0xcc, 0xd3, 0xc1, 0x58, 0xe4, 0x27, 0x33, 0x2d, 0xb8, 0x37, 0x52, 0x7e, - 0x16, 0xb9, 0xab, 0xb7, 0xd9, 0xc1, 0xeb, 0xc8, 0x79, 0xb9, 0xd3, 0xe6, 0x44, 0x13, 0x51, 0x2d, - 0xc6, 0x02, 0xe5, 0xe0, 0x3c, 0xa3, 0x15, 0x9b, 0x49, 0xae, 0x85, 0xbe, 0x8c, 0x84, 0xf9, 0x87, - 0x5d, 0x91, 0x9e, 0xf4, 0xf9, 0xf2, 0x8d, 0x81, 0x77, 0x7c, 0xfc, 0x60, 0x09, 0x48, 0x43, 0x2e, - 0xbb, 0xaf, 0xc9, 0xd6, 0x90, 0x2d, 0x40, 0x80, 0x59, 0xbd, 0x3b, 0x04, 0xda, 0x50, 0x2a, 0x53, - 0xf5, 0xc0, 0x97, 0x54, 0x04, 0x14, 0xb1, 0x8e, 0xd1, 0x6b, 0x53, 0x9e, 0xa4, 0xaa, 0x5e, 0x6e, - 0x1c, 0x11, 0x6b, 0x0a, 0xc4, 0xec, 0x5b, 0x77, 0xa8, 0x00, 0x83, 0x77, 0xdb, 0xf4, 0xfb, 0x00, - 0xf4, 0x06, 0x57, 0x25, 0x8e, 0x1c, 0x87, 0xb4, 0xbe, 0xb8, 0x04, 0x35, 0x93, 0x67, 0xaa, 0x36, - 0xa5, 0x62, 0xe4, 0xf6, 0xcb, 0xc8, 0xa6, 0x58, 0x77, 0x96, 0xc4, 0x6c, 0x0b, 0xc8, 0x41, 0xe2, - 0x36, 0x01, 0x94, 0xa5, 0xe9, 0x46, 0x17, 0xd3, 0x0b, 0x18, 0x7e, 0x06, 0x88, 0x9b, 0x7e, 0xdd, - 0x92, 0x20, 0xc6, 0xe3, 0x7e, 0xb1, 0x02, 0x81, 0x81, 0x00, 0xf5, 0xa6, 0xda, 0x32, 0xb9, 0x37, - 0x61, 0xe9, 0x7c, 0x99, 0xf7, 0x4a, 0x37, 0xee, 0x52, 0x30, 0x4f, 0xbf, 0x57, 0x6f, 0xfe, 0x20, - 0xdc, 0xa3, 0xfe, 0x51, 0xbf, 0x72, 0x13, 0x8a, 0xb1, 0xd7, 0x99, 0x7d, 0x67, 0xa8, 0xd4, 0xb0, - 0x35, 0x40, 0x7c, 0xc8, 0xdc, 0x03, 0x6b, 0x90, 0xb5, 0x65, 0x04, 0x7f, 0x97, 0x8b, 0xa8, 0x69, - 0x20, 0x04, 0xcb, 0x48, 0x39, 0xb7, 0x57, 0xe0, 0xd9, 0xbb, 0x15, 0xe1, 0x59, 0x16, 0xf3, 0xe1, - 0xab, 0x91, 0xea, 0x8a, 0x88, 0xad, 0x8d, 0xa3, 0x24, 0x4a, 0x35, 0xa5, 0xd2, 0x32, 0x19, 0x66, - 0xa8, 0xbb, 0x32, 0x9d, 0xf4, 0x94, 0x99, 0xc1, 0x2e, 0x2b, 0xf8, 0x98, 0x6a, 0x6e, 0x72, 0x77, - 0xd0, 0xc9, 0xfc, 0x5f, 0xd7, 0x69, 0xd1, 0x08, 0x12, 0xbf, 0x81, 0xc1, 0xa1, 0x1b, 0x3b, 0x41, - 0xb0, 0x24, 0x11, 0x0a, 0x65, 0xab, 0x81, 0x39, 0xb3, 0xd5, 0x02, 0x81, 0x81, 0x00, 0xea, 0x41, - 0xb5, 0xed, 0xac, 0xa0, 0x43, 0xd7, 0xde, 0x1e, 0x6b, 0x95, 0xbe, 0x88, 0x02, 0xaf, 0x2f, 0xbb, - 0x37, 0xf7, 0x2f, 0xf6, 0x4f, 0xa0, 0xaa, 0x43, 0x03, 0x7d, 0x33, 0xdd, 0x1e, 0x7a, 0xba, 0xa0, - 0x10, 0x77, 0x1f, 0x4a, 0xc9, 0x88, 0x58, 0x9d, 0x81, 0x3a, 0xe8, 0xac, 0x86, 0x2f, 0x80, 0x6c, - 0xc7, 0xa0, 0xe5, 0xed, 0x8d, 0x90, 0xa9, 0xa7, 0x36, 0x23, 0xd7, 0xb5, 0x89, 0xfc, 0xad, 0x4d, - 0xae, 0x0e, 0xec, 0xdc, 0xe7, 0x7e, 0x69, 0xfe, 0x62, 0x4b, 0x81, 0xfe, 0x52, 0x81, 0x77, 0x6a, - 0x35, 0xab, 0x52, 0x6f, 0x56, 0x41, 0x6c, 0x57, 0x3d, 0x75, 0x92, 0x14, 0x42, 0xa2, 0xc9, 0x50, - 0x52, 0x57, 0x9f, 0x26, 0x3c, 0xcd, 0x61, 0xa9, 0xda, 0x9b, 0x2c, 0xda, 0xc1, 0xd0, 0x26, 0x07, - 0x90, 0x15, 0x8c, 0x81, 0xe2, 0xde, 0xc0, 0x98, 0x58, 0x9d, 0x96, 0x0f, 0xcd, 0x55, 0x02, 0x81, - 0x81, 0x00, 0x87, 0xfb, 0xf8, 0x77, 0xf1, 0xcd, 0xf5, 0xb6, 0xa1, 0xd2, 0x3d, 0x71, 0x69, 0x6a, - 0xd5, 0x36, 0x87, 0x3e, 0xdd, 0xb1, 0x52, 0x55, 0x70, 0xae, 0x9b, 0x9f, 0x37, 0x42, 0x78, 0x0c, - 0xe4, 0x0b, 0xfc, 0x9c, 0xce, 0x20, 0x48, 0xb4, 0xce, 0x95, 0xc7, 0x3e, 0x0d, 0x85, 0x1b, 0x2b, - 0x7d, 0x2e, 0xd1, 0x81, 0xac, 0x2b, 0x94, 0x6b, 0xb5, 0x5c, 0xd2, 0x07, 0x46, 0x63, 0xf7, 0x12, - 0xb2, 0x94, 0xfd, 0x34, 0xc4, 0xf3, 0x8e, 0xc8, 0x13, 0x08, 0xf0, 0x74, 0x05, 0xdb, 0x45, 0x37, - 0xd5, 0x63, 0xfb, 0x34, 0xb3, 0x1a, 0x26, 0xb3, 0x8c, 0x9e, 0x2c, 0x14, 0x02, 0x8b, 0xac, 0x5d, - 0xa3, 0x28, 0x96, 0x32, 0x11, 0x60, 0xd8, 0x9e, 0xf9, 0x06, 0x87, 0x5d, 0xaa, 0xca, 0x99, 0xfb, - 0x45, 0x1d, 0x9c, 0x3f, 0xca, 0xe6, 0x5f, 0x34, 0x2a, 0xc4, 0x9c, 0x66, 0x4c, 0x07, 0xd7, 0xbe, - 0x50, 0x8d, 0x02, 0x81, 0x80, 0x51, 0xdb, 0x96, 0x6c, 0x30, 0x37, 0x6c, 0x9d, 0xa1, 0x43, 0x76, - 0x0a, 0xc4, 0xa2, 0x98, 0x75, 0x89, 0x33, 0x5d, 0xd2, 0x25, 0xd3, 0x67, 0x6d, 0xd8, 0x31, 0x44, - 0xa5, 0xda, 0x9a, 0xb9, 0x0c, 0xdf, 0xec, 0x10, 0xf4, 0xdf, 0x5d, 0x6d, 0xe1, 0x14, 0x3e, 0x2d, - 0xab, 0x5d, 0x24, 0xf4, 0x5a, 0xe3, 0x00, 0xa0, 0x1d, 0x8c, 0x5b, 0x1f, 0x6d, 0xde, 0xaa, 0xcc, - 0x93, 0x67, 0xcc, 0x4b, 0x24, 0x9d, 0x96, 0x98, 0x6d, 0x24, 0xbd, 0xe8, 0xb2, 0xd6, 0xed, 0x0a, - 0x82, 0x22, 0x31, 0xb1, 0xb9, 0x05, 0xf6, 0x7a, 0x3c, 0x9c, 0xb8, 0xc5, 0x26, 0x65, 0x6a, 0x72, - 0xd2, 0x83, 0xb2, 0x4a, 0xba, 0xc1, 0xa8, 0x2c, 0xad, 0xeb, 0xb2, 0x1b, 0xeb, 0x14, 0xe6, 0x9a, - 0xba, 0x40, 0xc9, 0x4c, 0x92, 0xa4, 0xc7, 0x5d, 0xc4, 0xf9, 0xed, 0x65, 0x4e, 0xbb, 0x74, 0x40, - 0xfb, 0x08, 0x36, 0x0b, 0x65, 0x02, 0x81, 0x81, 0x00, 0xeb, 0x60, 0x01, 0x21, 0x22, 0xa1, 0xde, - 0x89, 0x62, 0xfa, 0x68, 0x03, 0x09, 0xf1, 0xa6, 0x14, 0xf0, 0xbe, 0xf7, 0x71, 0x3a, 0x01, 0x85, - 0x1f, 0x2c, 0x86, 0xde, 0x4a, 0xfb, 0x35, 0x16, 0xc4, 0x84, 0x22, 0x83, 0x49, 0xeb, 0x0d, 0xf7, - 0x33, 0x47, 0x8f, 0x96, 0x37, 0x32, 0xd3, 0xd2, 0xec, 0xea, 0x0f, 0xd0, 0xde, 0x0d, 0x27, 0x9e, - 0xc1, 0xf1, 0xe0, 0x39, 0xa6, 0x3e, 0x6c, 0xd4, 0x39, 0xdf, 0xde, 0xbd, 0x4c, 0xb8, 0xe7, 0xb7, - 0x4e, 0x2a, 0x32, 0x92, 0x83, 0xd3, 0x12, 0xb9, 0xa1, 0x91, 0x52, 0x46, 0x24, 0x58, 0x05, 0x35, - 0x22, 0x5f, 0x10, 0x3c, 0x13, 0x5b, 0xbe, 0x47, 0x5e, 0xbf, 0x85, 0xd6, 0xac, 0xfc, 0xbb, 0xd9, - 0x91, 0xf9, 0x50, 0x8f, 0xfc, 0xc2, 0x2c, 0x81, 0x5c, 0xa5, 0xc3, 0xc2, 0x15, 0xbe, 0xf4, 0x72, - 0xfd, 0x4d, 0xf0, 0x10, 0x6f, 0xe5, 0xbf, 0x8c, 0xb1 + 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe0, 0xc9, 0x91, 0x62, + 0xcd, 0x91, 0x68, 0x75, 0x2c, 0x32, 0x7a, 0xdd, 0xf1, 0xd6, 0x64, 0x77, 0x8b, 0x72, 0x9e, 0x14, + 0x2a, 0x62, 0x08, 0xd1, 0x89, 0x7d, 0xe2, 0x17, 0xdc, 0xb3, 0xda, 0xbc, 0x3a, 0x9f, 0x84, 0x03, + 0xd3, 0x2e, 0x68, 0xbe, 0xc1, 0x57, 0xcb, 0x2a, 0xe2, 0xd6, 0xcf, 0xc4, 0x7f, 0xbd, 0x53, 0x3f, + 0xeb, 0x39, 0x98, 0x69, 0xb0, 0x40, 0x14, 0xbf, 0xf5, 0x5a, 0x23, 0x23, 0xf4, 0x4c, 0xf8, 0xf1, + 0x03, 0x56, 0x6d, 0x7d, 0x1b, 0x93, 0xd7, 0x0f, 0xc1, 0x8c, 0x70, 0xe0, 0x2c, 0x55, 0x7e, 0xa1, + 0xfc, 0x05, 0xe9, 0xd7, 0xea, 0xb1, 0x5c, 0x0f, 0x9b, 0xac, 0x6a, 0x2e, 0xb4, 0xc5, 0xbf, 0x41, + 0x8f, 0xda, 0xfc, 0x85, 0xc6, 0xaa, 0x25, 0xe4, 0xb9, 0x9a, 0xc6, 0xd8, 0x9a, 0x31, 0x8a, 0x17, + 0x8b, 0x8c, 0x4e, 0x20, 0xd9, 0x71, 0xfc, 0x66, 0x3a, 0xfd, 0x49, 0x95, 0x54, 0xa8, 0xaf, 0x42, + 0x5e, 0xba, 0x26, 0xe6, 0xd3, 0xa0, 0xd2, 0x02, 0x3b, 0x51, 0x8b, 0x39, 0xd3, 0x97, 0xd2, 0xe4, + 0xd1, 0x01, 0x65, 0xab, 0x8e, 0xa2, 0x80, 0x5b, 0x5e, 0xbb, 0x11, 0x7f, 0x50, 0x1b, 0x2b, 0x0d, + 0x20, 0x40, 0xb5, 0xbf, 0xd1, 0x32, 0xfa, 0x25, 0xe1, 0x0d, 0x75, 0xfc, 0x11, 0xcf, 0x21, 0xdd, + 0x45, 0x16, 0xe4, 0x56, 0x58, 0x49, 0x33, 0xca, 0xaf, 0xe3, 0x17, 0x7b, 0x7a, 0x8f, 0xb1, 0xec, + 0x1c, 0x4d, 0xa2, 0xc2, 0xce, 0x8b, 0x19, 0x4b, 0xc0, 0xc4, 0x36, 0x6a, 0x7c, 0x5b, 0x89, 0x14, + 0x98, 0xcb, 0xa9, 0xca, 0x66, 0xf2, 0xaa, 0xf9, 0x12, 0x40, 0x0e, 0x6a, 0x78, 0x4d, 0x1f, 0x54, + 0x3c, 0x03, 0x7a, 0x91, 0xf5, 0xb7, 0x3d, 0xe2, 0xfc, 0x65, 0xb7, 0xaa, 0xa9, 0x39, 0x68, 0xa7, + 0xdb, 0x29, 0xc1, 0x40, 0x0b, 0x4e, 0xfb, 0xce, 0x74, 0xa5, 0x46, 0xb9, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb4, 0xc8, 0x07, 0x60, 0x01, 0xd9, 0xb6, 0xbb, 0xbd, 0x8e, + 0xdf, 0x97, 0xcd, 0xde, 0x51, 0xb0, 0x7e, 0xfa, 0xf0, 0x3d, 0x61, 0x94, 0xb4, 0x68, 0xe8, 0x7d, + 0xd0, 0x2e, 0xc6, 0xb5, 0xf2, 0xed, 0xbc, 0xeb, 0xfb, 0x3d, 0x24, 0x43, 0x47, 0xc4, 0x5a, 0x34, + 0x64, 0x56, 0x1a, 0x57, 0x0e, 0x83, 0x87, 0x04, 0x59, 0x86, 0xa7, 0x84, 0x0b, 0x9a, 0xbc, 0x3f, + 0xdd, 0x30, 0x40, 0x7f, 0x7c, 0x91, 0x76, 0xf1, 0xcc, 0xa7, 0xf0, 0xba, 0x3a, 0x96, 0x0a, 0x6e, + 0xcc, 0xe0, 0x84, 0x15, 0x91, 0xd6, 0x08, 0x71, 0xbd, 0xc5, 0x42, 0xad, 0xf2, 0xd2, 0x4e, 0x92, + 0xd3, 0x6a, 0x4e, 0x15, 0xcc, 0xd3, 0xc1, 0x58, 0xe4, 0x27, 0x33, 0x2d, 0xb8, 0x37, 0x52, 0x7e, + 0x16, 0xb9, 0xab, 0xb7, 0xd9, 0xc1, 0xeb, 0xc8, 0x79, 0xb9, 0xd3, 0xe6, 0x44, 0x13, 0x51, 0x2d, + 0xc6, 0x02, 0xe5, 0xe0, 0x3c, 0xa3, 0x15, 0x9b, 0x49, 0xae, 0x85, 0xbe, 0x8c, 0x84, 0xf9, 0x87, + 0x5d, 0x91, 0x9e, 0xf4, 0xf9, 0xf2, 0x8d, 0x81, 0x77, 0x7c, 0xfc, 0x60, 0x09, 0x48, 0x43, 0x2e, + 0xbb, 0xaf, 0xc9, 0xd6, 0x90, 0x2d, 0x40, 0x80, 0x59, 0xbd, 0x3b, 0x04, 0xda, 0x50, 0x2a, 0x53, + 0xf5, 0xc0, 0x97, 0x54, 0x04, 0x14, 0xb1, 0x8e, 0xd1, 0x6b, 0x53, 0x9e, 0xa4, 0xaa, 0x5e, 0x6e, + 0x1c, 0x11, 0x6b, 0x0a, 0xc4, 0xec, 0x5b, 0x77, 0xa8, 0x00, 0x83, 0x77, 0xdb, 0xf4, 0xfb, 0x00, + 0xf4, 0x06, 0x57, 0x25, 0x8e, 0x1c, 0x87, 0xb4, 0xbe, 0xb8, 0x04, 0x35, 0x93, 0x67, 0xaa, 0x36, + 0xa5, 0x62, 0xe4, 0xf6, 0xcb, 0xc8, 0xa6, 0x58, 0x77, 0x96, 0xc4, 0x6c, 0x0b, 0xc8, 0x41, 0xe2, + 0x36, 0x01, 0x94, 0xa5, 0xe9, 0x46, 0x17, 0xd3, 0x0b, 0x18, 0x7e, 0x06, 0x88, 0x9b, 0x7e, 0xdd, + 0x92, 0x20, 0xc6, 0xe3, 0x7e, 0xb1, 0x02, 0x81, 0x81, 0x00, 0xf5, 0xa6, 0xda, 0x32, 0xb9, 0x37, + 0x61, 0xe9, 0x7c, 0x99, 0xf7, 0x4a, 0x37, 0xee, 0x52, 0x30, 0x4f, 0xbf, 0x57, 0x6f, 0xfe, 0x20, + 0xdc, 0xa3, 0xfe, 0x51, 0xbf, 0x72, 0x13, 0x8a, 0xb1, 0xd7, 0x99, 0x7d, 0x67, 0xa8, 0xd4, 0xb0, + 0x35, 0x40, 0x7c, 0xc8, 0xdc, 0x03, 0x6b, 0x90, 0xb5, 0x65, 0x04, 0x7f, 0x97, 0x8b, 0xa8, 0x69, + 0x20, 0x04, 0xcb, 0x48, 0x39, 0xb7, 0x57, 0xe0, 0xd9, 0xbb, 0x15, 0xe1, 0x59, 0x16, 0xf3, 0xe1, + 0xab, 0x91, 0xea, 0x8a, 0x88, 0xad, 0x8d, 0xa3, 0x24, 0x4a, 0x35, 0xa5, 0xd2, 0x32, 0x19, 0x66, + 0xa8, 0xbb, 0x32, 0x9d, 0xf4, 0x94, 0x99, 0xc1, 0x2e, 0x2b, 0xf8, 0x98, 0x6a, 0x6e, 0x72, 0x77, + 0xd0, 0xc9, 0xfc, 0x5f, 0xd7, 0x69, 0xd1, 0x08, 0x12, 0xbf, 0x81, 0xc1, 0xa1, 0x1b, 0x3b, 0x41, + 0xb0, 0x24, 0x11, 0x0a, 0x65, 0xab, 0x81, 0x39, 0xb3, 0xd5, 0x02, 0x81, 0x81, 0x00, 0xea, 0x41, + 0xb5, 0xed, 0xac, 0xa0, 0x43, 0xd7, 0xde, 0x1e, 0x6b, 0x95, 0xbe, 0x88, 0x02, 0xaf, 0x2f, 0xbb, + 0x37, 0xf7, 0x2f, 0xf6, 0x4f, 0xa0, 0xaa, 0x43, 0x03, 0x7d, 0x33, 0xdd, 0x1e, 0x7a, 0xba, 0xa0, + 0x10, 0x77, 0x1f, 0x4a, 0xc9, 0x88, 0x58, 0x9d, 0x81, 0x3a, 0xe8, 0xac, 0x86, 0x2f, 0x80, 0x6c, + 0xc7, 0xa0, 0xe5, 0xed, 0x8d, 0x90, 0xa9, 0xa7, 0x36, 0x23, 0xd7, 0xb5, 0x89, 0xfc, 0xad, 0x4d, + 0xae, 0x0e, 0xec, 0xdc, 0xe7, 0x7e, 0x69, 0xfe, 0x62, 0x4b, 0x81, 0xfe, 0x52, 0x81, 0x77, 0x6a, + 0x35, 0xab, 0x52, 0x6f, 0x56, 0x41, 0x6c, 0x57, 0x3d, 0x75, 0x92, 0x14, 0x42, 0xa2, 0xc9, 0x50, + 0x52, 0x57, 0x9f, 0x26, 0x3c, 0xcd, 0x61, 0xa9, 0xda, 0x9b, 0x2c, 0xda, 0xc1, 0xd0, 0x26, 0x07, + 0x90, 0x15, 0x8c, 0x81, 0xe2, 0xde, 0xc0, 0x98, 0x58, 0x9d, 0x96, 0x0f, 0xcd, 0x55, 0x02, 0x81, + 0x81, 0x00, 0x87, 0xfb, 0xf8, 0x77, 0xf1, 0xcd, 0xf5, 0xb6, 0xa1, 0xd2, 0x3d, 0x71, 0x69, 0x6a, + 0xd5, 0x36, 0x87, 0x3e, 0xdd, 0xb1, 0x52, 0x55, 0x70, 0xae, 0x9b, 0x9f, 0x37, 0x42, 0x78, 0x0c, + 0xe4, 0x0b, 0xfc, 0x9c, 0xce, 0x20, 0x48, 0xb4, 0xce, 0x95, 0xc7, 0x3e, 0x0d, 0x85, 0x1b, 0x2b, + 0x7d, 0x2e, 0xd1, 0x81, 0xac, 0x2b, 0x94, 0x6b, 0xb5, 0x5c, 0xd2, 0x07, 0x46, 0x63, 0xf7, 0x12, + 0xb2, 0x94, 0xfd, 0x34, 0xc4, 0xf3, 0x8e, 0xc8, 0x13, 0x08, 0xf0, 0x74, 0x05, 0xdb, 0x45, 0x37, + 0xd5, 0x63, 0xfb, 0x34, 0xb3, 0x1a, 0x26, 0xb3, 0x8c, 0x9e, 0x2c, 0x14, 0x02, 0x8b, 0xac, 0x5d, + 0xa3, 0x28, 0x96, 0x32, 0x11, 0x60, 0xd8, 0x9e, 0xf9, 0x06, 0x87, 0x5d, 0xaa, 0xca, 0x99, 0xfb, + 0x45, 0x1d, 0x9c, 0x3f, 0xca, 0xe6, 0x5f, 0x34, 0x2a, 0xc4, 0x9c, 0x66, 0x4c, 0x07, 0xd7, 0xbe, + 0x50, 0x8d, 0x02, 0x81, 0x80, 0x51, 0xdb, 0x96, 0x6c, 0x30, 0x37, 0x6c, 0x9d, 0xa1, 0x43, 0x76, + 0x0a, 0xc4, 0xa2, 0x98, 0x75, 0x89, 0x33, 0x5d, 0xd2, 0x25, 0xd3, 0x67, 0x6d, 0xd8, 0x31, 0x44, + 0xa5, 0xda, 0x9a, 0xb9, 0x0c, 0xdf, 0xec, 0x10, 0xf4, 0xdf, 0x5d, 0x6d, 0xe1, 0x14, 0x3e, 0x2d, + 0xab, 0x5d, 0x24, 0xf4, 0x5a, 0xe3, 0x00, 0xa0, 0x1d, 0x8c, 0x5b, 0x1f, 0x6d, 0xde, 0xaa, 0xcc, + 0x93, 0x67, 0xcc, 0x4b, 0x24, 0x9d, 0x96, 0x98, 0x6d, 0x24, 0xbd, 0xe8, 0xb2, 0xd6, 0xed, 0x0a, + 0x82, 0x22, 0x31, 0xb1, 0xb9, 0x05, 0xf6, 0x7a, 0x3c, 0x9c, 0xb8, 0xc5, 0x26, 0x65, 0x6a, 0x72, + 0xd2, 0x83, 0xb2, 0x4a, 0xba, 0xc1, 0xa8, 0x2c, 0xad, 0xeb, 0xb2, 0x1b, 0xeb, 0x14, 0xe6, 0x9a, + 0xba, 0x40, 0xc9, 0x4c, 0x92, 0xa4, 0xc7, 0x5d, 0xc4, 0xf9, 0xed, 0x65, 0x4e, 0xbb, 0x74, 0x40, + 0xfb, 0x08, 0x36, 0x0b, 0x65, 0x02, 0x81, 0x81, 0x00, 0xeb, 0x60, 0x01, 0x21, 0x22, 0xa1, 0xde, + 0x89, 0x62, 0xfa, 0x68, 0x03, 0x09, 0xf1, 0xa6, 0x14, 0xf0, 0xbe, 0xf7, 0x71, 0x3a, 0x01, 0x85, + 0x1f, 0x2c, 0x86, 0xde, 0x4a, 0xfb, 0x35, 0x16, 0xc4, 0x84, 0x22, 0x83, 0x49, 0xeb, 0x0d, 0xf7, + 0x33, 0x47, 0x8f, 0x96, 0x37, 0x32, 0xd3, 0xd2, 0xec, 0xea, 0x0f, 0xd0, 0xde, 0x0d, 0x27, 0x9e, + 0xc1, 0xf1, 0xe0, 0x39, 0xa6, 0x3e, 0x6c, 0xd4, 0x39, 0xdf, 0xde, 0xbd, 0x4c, 0xb8, 0xe7, 0xb7, + 0x4e, 0x2a, 0x32, 0x92, 0x83, 0xd3, 0x12, 0xb9, 0xa1, 0x91, 0x52, 0x46, 0x24, 0x58, 0x05, 0x35, + 0x22, 0x5f, 0x10, 0x3c, 0x13, 0x5b, 0xbe, 0x47, 0x5e, 0xbf, 0x85, 0xd6, 0xac, 0xfc, 0xbb, 0xd9, + 0x91, 0xf9, 0x50, 0x8f, 0xfc, 0xc2, 0x2c, 0x81, 0x5c, 0xa5, 0xc3, 0xc2, 0x15, 0xbe, 0xf4, 0x72, + 0xfd, 0x4d, 0xf0, 0x10, 0x6f, 0xe5, 0xbf, 0x8c, 0xb1 }; #define CERT_DER_LENGTH 968 UA_Byte CERT_DER_DATA[968] = { - 0x30, 0x82, 0x03, 0xc4, 0x30, 0x82, 0x02, 0xac, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, - 0xa7, 0x17, 0x44, 0x2f, 0x8e, 0x6b, 0x74, 0xba, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, - 0x09, 0x6f, 0x70, 0x65, 0x6e, 0x36, 0x32, 0x35, 0x34, 0x31, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x0c, 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x36, 0x32, 0x35, 0x34, 0x31, 0x2e, 0x6f, - 0x72, 0x67, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x33, 0x32, 0x38, 0x30, 0x38, 0x33, 0x33, - 0x35, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x33, 0x32, 0x35, 0x30, 0x38, 0x33, 0x33, 0x35, - 0x37, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, - 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x6f, 0x70, 0x65, 0x6e, - 0x36, 0x32, 0x35, 0x34, 0x31, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, - 0x6f, 0x70, 0x65, 0x6e, 0x36, 0x32, 0x35, 0x34, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x40, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, - 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe0, 0xc9, 0x91, 0x62, 0xcd, 0x91, - 0x68, 0x75, 0x2c, 0x32, 0x7a, 0xdd, 0xf1, 0xd6, 0x64, 0x77, 0x8b, 0x72, 0x9e, 0x14, 0x2a, 0x62, - 0x08, 0xd1, 0x89, 0x7d, 0xe2, 0x17, 0xdc, 0xb3, 0xda, 0xbc, 0x3a, 0x9f, 0x84, 0x03, 0xd3, 0x2e, - 0x68, 0xbe, 0xc1, 0x57, 0xcb, 0x2a, 0xe2, 0xd6, 0xcf, 0xc4, 0x7f, 0xbd, 0x53, 0x3f, 0xeb, 0x39, - 0x98, 0x69, 0xb0, 0x40, 0x14, 0xbf, 0xf5, 0x5a, 0x23, 0x23, 0xf4, 0x4c, 0xf8, 0xf1, 0x03, 0x56, - 0x6d, 0x7d, 0x1b, 0x93, 0xd7, 0x0f, 0xc1, 0x8c, 0x70, 0xe0, 0x2c, 0x55, 0x7e, 0xa1, 0xfc, 0x05, - 0xe9, 0xd7, 0xea, 0xb1, 0x5c, 0x0f, 0x9b, 0xac, 0x6a, 0x2e, 0xb4, 0xc5, 0xbf, 0x41, 0x8f, 0xda, - 0xfc, 0x85, 0xc6, 0xaa, 0x25, 0xe4, 0xb9, 0x9a, 0xc6, 0xd8, 0x9a, 0x31, 0x8a, 0x17, 0x8b, 0x8c, - 0x4e, 0x20, 0xd9, 0x71, 0xfc, 0x66, 0x3a, 0xfd, 0x49, 0x95, 0x54, 0xa8, 0xaf, 0x42, 0x5e, 0xba, - 0x26, 0xe6, 0xd3, 0xa0, 0xd2, 0x02, 0x3b, 0x51, 0x8b, 0x39, 0xd3, 0x97, 0xd2, 0xe4, 0xd1, 0x01, - 0x65, 0xab, 0x8e, 0xa2, 0x80, 0x5b, 0x5e, 0xbb, 0x11, 0x7f, 0x50, 0x1b, 0x2b, 0x0d, 0x20, 0x40, - 0xb5, 0xbf, 0xd1, 0x32, 0xfa, 0x25, 0xe1, 0x0d, 0x75, 0xfc, 0x11, 0xcf, 0x21, 0xdd, 0x45, 0x16, - 0xe4, 0x56, 0x58, 0x49, 0x33, 0xca, 0xaf, 0xe3, 0x17, 0x7b, 0x7a, 0x8f, 0xb1, 0xec, 0x1c, 0x4d, - 0xa2, 0xc2, 0xce, 0x8b, 0x19, 0x4b, 0xc0, 0xc4, 0x36, 0x6a, 0x7c, 0x5b, 0x89, 0x14, 0x98, 0xcb, - 0xa9, 0xca, 0x66, 0xf2, 0xaa, 0xf9, 0x12, 0x40, 0x0e, 0x6a, 0x78, 0x4d, 0x1f, 0x54, 0x3c, 0x03, - 0x7a, 0x91, 0xf5, 0xb7, 0x3d, 0xe2, 0xfc, 0x65, 0xb7, 0xaa, 0xa9, 0x39, 0x68, 0xa7, 0xdb, 0x29, - 0xc1, 0x40, 0x0b, 0x4e, 0xfb, 0xce, 0x74, 0xa5, 0x46, 0xb9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, - 0x81, 0xc2, 0x30, 0x81, 0xbf, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0x60, 0x6e, 0x44, 0x94, 0xa8, 0xa2, 0x4e, 0x7a, 0x3e, 0xe2, 0x4b, 0x84, 0x5e, 0xec, 0x01, 0xc9, - 0xa3, 0xf9, 0x69, 0xaf, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, - 0x14, 0x53, 0x77, 0xe0, 0xa2, 0xf2, 0x49, 0x38, 0xcf, 0x71, 0x58, 0x0a, 0x67, 0xa6, 0xc0, 0x17, - 0xd7, 0xb5, 0xdc, 0x52, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, - 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xe0, 0x30, 0x1d, 0x06, - 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, 0x03, - 0x55, 0x1d, 0x11, 0x04, 0x3f, 0x30, 0x3d, 0x82, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, - 0x73, 0x74, 0x82, 0x06, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x87, 0x04, 0x7f, 0x00, 0x00, 0x01, - 0x87, 0x04, 0x00, 0x00, 0x00, 0x00, 0x86, 0x1c, 0x75, 0x72, 0x6e, 0x3a, 0x75, 0x6e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x3a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa4, 0xc1, 0x4f, 0x0e, 0xfe, 0xce, 0x2d, 0x91, - 0x8a, 0x51, 0x25, 0xd2, 0x6c, 0x07, 0x86, 0x95, 0xba, 0xc5, 0xe0, 0xad, 0x9b, 0x09, 0x3e, 0x7f, - 0x36, 0xc4, 0xa8, 0x10, 0x5b, 0x33, 0x77, 0xe5, 0xb5, 0x3b, 0xd8, 0x98, 0x7c, 0x42, 0x05, 0xcb, - 0xb7, 0x91, 0x07, 0x3f, 0x47, 0xff, 0x13, 0x15, 0x45, 0xff, 0x05, 0x03, 0x3d, 0xed, 0x63, 0x96, - 0x3a, 0x5c, 0xf8, 0x59, 0xd0, 0xbc, 0x68, 0x8c, 0xfb, 0xf8, 0x29, 0x07, 0x76, 0x63, 0xa7, 0x39, - 0xc1, 0x82, 0xc1, 0x10, 0x8b, 0x17, 0xf2, 0x1d, 0x14, 0xdd, 0x88, 0xe7, 0xdc, 0x2f, 0xa7, 0x9d, - 0xa3, 0xaa, 0xfd, 0x1a, 0x70, 0xce, 0x57, 0xb5, 0x9f, 0xc3, 0x7b, 0xd0, 0xc0, 0x6f, 0x73, 0x81, - 0x74, 0x41, 0x93, 0x0d, 0x0d, 0x1a, 0x95, 0xf6, 0xe4, 0x1c, 0x04, 0x2b, 0x37, 0x4f, 0xf9, 0x99, - 0x82, 0x57, 0xf0, 0x4f, 0x14, 0xcb, 0x0f, 0x3d, 0x1a, 0x52, 0x69, 0x18, 0x3f, 0xbe, 0x1c, 0x1c, - 0x1b, 0xca, 0xbd, 0xe7, 0xe0, 0x81, 0x44, 0x6d, 0x4a, 0x08, 0x8a, 0xe2, 0x7e, 0x59, 0x9f, 0x89, - 0x44, 0x7e, 0x4d, 0xaf, 0x5a, 0x8e, 0xe8, 0xd2, 0x2e, 0x98, 0x72, 0x86, 0xef, 0x7b, 0xcf, 0x88, - 0xd0, 0xe2, 0xd5, 0xd9, 0xd5, 0x19, 0xa2, 0x8c, 0xf4, 0x40, 0x98, 0x86, 0x32, 0x9f, 0x3e, 0x25, - 0x05, 0xd0, 0xdc, 0xf8, 0x1a, 0x0f, 0xdf, 0xc0, 0x54, 0x46, 0x20, 0xbd, 0xd4, 0xf6, 0xf5, 0xdd, - 0x10, 0x2e, 0xa7, 0x1a, 0xf4, 0xbb, 0xed, 0x5d, 0xf3, 0x1c, 0x96, 0x44, 0x81, 0x69, 0xd4, 0x0b, - 0xbe, 0x59, 0x07, 0x1b, 0x7f, 0x93, 0xc3, 0x4e, 0x7b, 0x32, 0x51, 0xd0, 0x13, 0x47, 0x57, 0x52, - 0xf0, 0x5c, 0x54, 0x36, 0x22, 0xb6, 0xf5, 0x67, 0xbb, 0xd3, 0xa6, 0x43, 0xf0, 0xca, 0x98, 0x91, - 0xda, 0x31, 0x3e, 0xd2, 0x8c, 0xfe, 0xd7, 0x51 + 0x30, 0x82, 0x03, 0xc4, 0x30, 0x82, 0x02, 0xac, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0xa7, 0x17, 0x44, 0x2f, 0x8e, 0x6b, 0x74, 0xba, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x39, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x44, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x09, 0x6f, 0x70, 0x65, 0x6e, 0x36, 0x32, 0x35, 0x34, 0x31, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x36, 0x32, 0x35, 0x34, 0x31, 0x2e, 0x6f, + 0x72, 0x67, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x33, 0x32, 0x38, 0x30, 0x38, 0x33, 0x33, + 0x35, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x33, 0x32, 0x35, 0x30, 0x38, 0x33, 0x33, 0x35, + 0x37, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, + 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x6f, 0x70, 0x65, 0x6e, + 0x36, 0x32, 0x35, 0x34, 0x31, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, + 0x6f, 0x70, 0x65, 0x6e, 0x36, 0x32, 0x35, 0x34, 0x31, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x40, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, + 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe0, 0xc9, 0x91, 0x62, 0xcd, 0x91, + 0x68, 0x75, 0x2c, 0x32, 0x7a, 0xdd, 0xf1, 0xd6, 0x64, 0x77, 0x8b, 0x72, 0x9e, 0x14, 0x2a, 0x62, + 0x08, 0xd1, 0x89, 0x7d, 0xe2, 0x17, 0xdc, 0xb3, 0xda, 0xbc, 0x3a, 0x9f, 0x84, 0x03, 0xd3, 0x2e, + 0x68, 0xbe, 0xc1, 0x57, 0xcb, 0x2a, 0xe2, 0xd6, 0xcf, 0xc4, 0x7f, 0xbd, 0x53, 0x3f, 0xeb, 0x39, + 0x98, 0x69, 0xb0, 0x40, 0x14, 0xbf, 0xf5, 0x5a, 0x23, 0x23, 0xf4, 0x4c, 0xf8, 0xf1, 0x03, 0x56, + 0x6d, 0x7d, 0x1b, 0x93, 0xd7, 0x0f, 0xc1, 0x8c, 0x70, 0xe0, 0x2c, 0x55, 0x7e, 0xa1, 0xfc, 0x05, + 0xe9, 0xd7, 0xea, 0xb1, 0x5c, 0x0f, 0x9b, 0xac, 0x6a, 0x2e, 0xb4, 0xc5, 0xbf, 0x41, 0x8f, 0xda, + 0xfc, 0x85, 0xc6, 0xaa, 0x25, 0xe4, 0xb9, 0x9a, 0xc6, 0xd8, 0x9a, 0x31, 0x8a, 0x17, 0x8b, 0x8c, + 0x4e, 0x20, 0xd9, 0x71, 0xfc, 0x66, 0x3a, 0xfd, 0x49, 0x95, 0x54, 0xa8, 0xaf, 0x42, 0x5e, 0xba, + 0x26, 0xe6, 0xd3, 0xa0, 0xd2, 0x02, 0x3b, 0x51, 0x8b, 0x39, 0xd3, 0x97, 0xd2, 0xe4, 0xd1, 0x01, + 0x65, 0xab, 0x8e, 0xa2, 0x80, 0x5b, 0x5e, 0xbb, 0x11, 0x7f, 0x50, 0x1b, 0x2b, 0x0d, 0x20, 0x40, + 0xb5, 0xbf, 0xd1, 0x32, 0xfa, 0x25, 0xe1, 0x0d, 0x75, 0xfc, 0x11, 0xcf, 0x21, 0xdd, 0x45, 0x16, + 0xe4, 0x56, 0x58, 0x49, 0x33, 0xca, 0xaf, 0xe3, 0x17, 0x7b, 0x7a, 0x8f, 0xb1, 0xec, 0x1c, 0x4d, + 0xa2, 0xc2, 0xce, 0x8b, 0x19, 0x4b, 0xc0, 0xc4, 0x36, 0x6a, 0x7c, 0x5b, 0x89, 0x14, 0x98, 0xcb, + 0xa9, 0xca, 0x66, 0xf2, 0xaa, 0xf9, 0x12, 0x40, 0x0e, 0x6a, 0x78, 0x4d, 0x1f, 0x54, 0x3c, 0x03, + 0x7a, 0x91, 0xf5, 0xb7, 0x3d, 0xe2, 0xfc, 0x65, 0xb7, 0xaa, 0xa9, 0x39, 0x68, 0xa7, 0xdb, 0x29, + 0xc1, 0x40, 0x0b, 0x4e, 0xfb, 0xce, 0x74, 0xa5, 0x46, 0xb9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, + 0x81, 0xc2, 0x30, 0x81, 0xbf, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x60, 0x6e, 0x44, 0x94, 0xa8, 0xa2, 0x4e, 0x7a, 0x3e, 0xe2, 0x4b, 0x84, 0x5e, 0xec, 0x01, 0xc9, + 0xa3, 0xf9, 0x69, 0xaf, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0x53, 0x77, 0xe0, 0xa2, 0xf2, 0x49, 0x38, 0xcf, 0x71, 0x58, 0x0a, 0x67, 0xa6, 0xc0, 0x17, + 0xd7, 0xb5, 0xdc, 0x52, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, + 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xe0, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x46, 0x06, 0x03, + 0x55, 0x1d, 0x11, 0x04, 0x3f, 0x30, 0x3d, 0x82, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, + 0x73, 0x74, 0x82, 0x06, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x87, 0x04, 0x7f, 0x00, 0x00, 0x01, + 0x87, 0x04, 0x00, 0x00, 0x00, 0x00, 0x86, 0x1c, 0x75, 0x72, 0x6e, 0x3a, 0x75, 0x6e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x3a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xa4, 0xc1, 0x4f, 0x0e, 0xfe, 0xce, 0x2d, 0x91, + 0x8a, 0x51, 0x25, 0xd2, 0x6c, 0x07, 0x86, 0x95, 0xba, 0xc5, 0xe0, 0xad, 0x9b, 0x09, 0x3e, 0x7f, + 0x36, 0xc4, 0xa8, 0x10, 0x5b, 0x33, 0x77, 0xe5, 0xb5, 0x3b, 0xd8, 0x98, 0x7c, 0x42, 0x05, 0xcb, + 0xb7, 0x91, 0x07, 0x3f, 0x47, 0xff, 0x13, 0x15, 0x45, 0xff, 0x05, 0x03, 0x3d, 0xed, 0x63, 0x96, + 0x3a, 0x5c, 0xf8, 0x59, 0xd0, 0xbc, 0x68, 0x8c, 0xfb, 0xf8, 0x29, 0x07, 0x76, 0x63, 0xa7, 0x39, + 0xc1, 0x82, 0xc1, 0x10, 0x8b, 0x17, 0xf2, 0x1d, 0x14, 0xdd, 0x88, 0xe7, 0xdc, 0x2f, 0xa7, 0x9d, + 0xa3, 0xaa, 0xfd, 0x1a, 0x70, 0xce, 0x57, 0xb5, 0x9f, 0xc3, 0x7b, 0xd0, 0xc0, 0x6f, 0x73, 0x81, + 0x74, 0x41, 0x93, 0x0d, 0x0d, 0x1a, 0x95, 0xf6, 0xe4, 0x1c, 0x04, 0x2b, 0x37, 0x4f, 0xf9, 0x99, + 0x82, 0x57, 0xf0, 0x4f, 0x14, 0xcb, 0x0f, 0x3d, 0x1a, 0x52, 0x69, 0x18, 0x3f, 0xbe, 0x1c, 0x1c, + 0x1b, 0xca, 0xbd, 0xe7, 0xe0, 0x81, 0x44, 0x6d, 0x4a, 0x08, 0x8a, 0xe2, 0x7e, 0x59, 0x9f, 0x89, + 0x44, 0x7e, 0x4d, 0xaf, 0x5a, 0x8e, 0xe8, 0xd2, 0x2e, 0x98, 0x72, 0x86, 0xef, 0x7b, 0xcf, 0x88, + 0xd0, 0xe2, 0xd5, 0xd9, 0xd5, 0x19, 0xa2, 0x8c, 0xf4, 0x40, 0x98, 0x86, 0x32, 0x9f, 0x3e, 0x25, + 0x05, 0xd0, 0xdc, 0xf8, 0x1a, 0x0f, 0xdf, 0xc0, 0x54, 0x46, 0x20, 0xbd, 0xd4, 0xf6, 0xf5, 0xdd, + 0x10, 0x2e, 0xa7, 0x1a, 0xf4, 0xbb, 0xed, 0x5d, 0xf3, 0x1c, 0x96, 0x44, 0x81, 0x69, 0xd4, 0x0b, + 0xbe, 0x59, 0x07, 0x1b, 0x7f, 0x93, 0xc3, 0x4e, 0x7b, 0x32, 0x51, 0xd0, 0x13, 0x47, 0x57, 0x52, + 0xf0, 0x5c, 0x54, 0x36, 0x22, 0xb6, 0xf5, 0x67, 0xbb, 0xd3, 0xa6, 0x43, 0xf0, 0xca, 0x98, 0x91, + 0xda, 0x31, 0x3e, 0xd2, 0x8c, 0xfe, 0xd7, 0x51 }; #define KEY_PEM_LENGTH 1679 @@ -348,6 +348,906 @@ UA_Byte CERT_PEM_DATA[1367] = { 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a }; +/* Generated from KEY_PEM_DATA via: openssl pkcs8 -topk8 -v2 des3 -in key.pem -out key-password.pem + The password is pass1234 */ +#define KEY_PEM_PASSWORD_LENGTH 1854 +UA_Byte KEY_PEM_PASSWORD_DATA[KEY_PEM_PASSWORD_LENGTH] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x45, 0x4e, 0x43, 0x52, 0x59, + 0x50, 0x54, 0x45, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x46, 0x48, 0x44, 0x42, 0x4f, 0x42, 0x67, + 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x42, 0x51, 0x30, 0x77, 0x51, 0x54, + 0x41, 0x70, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x42, 0x51, + 0x77, 0x77, 0x48, 0x41, 0x51, 0x49, 0x71, 0x77, 0x7a, 0x47, 0x38, 0x51, 0x68, 0x69, 0x56, 0x58, + 0x38, 0x43, 0x41, 0x67, 0x67, 0x41, 0x0a, 0x4d, 0x41, 0x77, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, + 0x49, 0x62, 0x33, 0x44, 0x51, 0x49, 0x4a, 0x42, 0x51, 0x41, 0x77, 0x46, 0x41, 0x59, 0x49, 0x4b, + 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x77, 0x63, 0x45, 0x43, 0x4a, 0x5a, 0x52, 0x51, + 0x57, 0x78, 0x4c, 0x47, 0x62, 0x31, 0x39, 0x42, 0x49, 0x49, 0x45, 0x79, 0x4e, 0x7a, 0x72, 0x52, + 0x4b, 0x31, 0x77, 0x4b, 0x42, 0x65, 0x51, 0x0a, 0x59, 0x48, 0x48, 0x36, 0x45, 0x37, 0x45, 0x7a, + 0x5a, 0x67, 0x43, 0x57, 0x4f, 0x64, 0x62, 0x53, 0x7a, 0x30, 0x44, 0x50, 0x78, 0x33, 0x52, 0x6a, + 0x48, 0x6c, 0x62, 0x53, 0x67, 0x48, 0x64, 0x30, 0x55, 0x34, 0x6f, 0x36, 0x4f, 0x76, 0x74, 0x71, + 0x31, 0x36, 0x55, 0x46, 0x43, 0x4c, 0x65, 0x74, 0x77, 0x4d, 0x6e, 0x30, 0x35, 0x72, 0x56, 0x41, + 0x68, 0x4c, 0x61, 0x44, 0x73, 0x39, 0x43, 0x75, 0x0a, 0x61, 0x65, 0x7a, 0x78, 0x42, 0x4d, 0x4a, + 0x77, 0x78, 0x77, 0x37, 0x6d, 0x32, 0x43, 0x4b, 0x42, 0x6f, 0x49, 0x79, 0x33, 0x41, 0x41, 0x39, + 0x47, 0x46, 0x58, 0x49, 0x5a, 0x71, 0x79, 0x75, 0x37, 0x63, 0x65, 0x5a, 0x4e, 0x52, 0x36, 0x64, + 0x53, 0x39, 0x4c, 0x49, 0x50, 0x73, 0x73, 0x71, 0x75, 0x54, 0x4f, 0x54, 0x76, 0x76, 0x48, 0x6f, + 0x4b, 0x45, 0x6a, 0x64, 0x30, 0x56, 0x51, 0x71, 0x42, 0x0a, 0x33, 0x66, 0x66, 0x38, 0x5a, 0x72, + 0x4d, 0x49, 0x6a, 0x2b, 0x33, 0x7a, 0x43, 0x4b, 0x6f, 0x78, 0x45, 0x62, 0x38, 0x38, 0x50, 0x70, + 0x68, 0x54, 0x61, 0x65, 0x75, 0x31, 0x62, 0x4e, 0x66, 0x6c, 0x49, 0x72, 0x6a, 0x79, 0x79, 0x78, + 0x70, 0x30, 0x4c, 0x5a, 0x79, 0x45, 0x36, 0x51, 0x75, 0x66, 0x75, 0x76, 0x4c, 0x42, 0x72, 0x4a, + 0x53, 0x66, 0x41, 0x46, 0x4c, 0x71, 0x63, 0x32, 0x6d, 0x4e, 0x0a, 0x45, 0x45, 0x45, 0x5a, 0x55, + 0x79, 0x43, 0x77, 0x74, 0x78, 0x4e, 0x6d, 0x31, 0x42, 0x2f, 0x37, 0x75, 0x52, 0x2b, 0x72, 0x36, + 0x2f, 0x50, 0x64, 0x36, 0x74, 0x58, 0x6c, 0x2f, 0x57, 0x6d, 0x45, 0x47, 0x4c, 0x68, 0x76, 0x2b, + 0x36, 0x45, 0x52, 0x58, 0x74, 0x35, 0x61, 0x61, 0x61, 0x39, 0x47, 0x51, 0x30, 0x67, 0x32, 0x78, + 0x7a, 0x4a, 0x42, 0x36, 0x54, 0x50, 0x30, 0x41, 0x5a, 0x45, 0x6d, 0x0a, 0x73, 0x7a, 0x42, 0x4a, + 0x72, 0x62, 0x4f, 0x31, 0x4e, 0x57, 0x79, 0x73, 0x33, 0x6e, 0x5a, 0x4f, 0x65, 0x64, 0x31, 0x2f, + 0x46, 0x49, 0x38, 0x43, 0x6e, 0x42, 0x55, 0x32, 0x4b, 0x6f, 0x61, 0x62, 0x67, 0x65, 0x6b, 0x6c, + 0x64, 0x37, 0x69, 0x61, 0x39, 0x61, 0x58, 0x4b, 0x5a, 0x54, 0x65, 0x76, 0x44, 0x78, 0x70, 0x46, + 0x4b, 0x75, 0x61, 0x36, 0x73, 0x35, 0x77, 0x43, 0x75, 0x58, 0x32, 0x4a, 0x0a, 0x54, 0x4d, 0x2b, + 0x41, 0x43, 0x76, 0x46, 0x65, 0x6d, 0x52, 0x71, 0x71, 0x68, 0x4f, 0x48, 0x6c, 0x69, 0x43, 0x4d, + 0x65, 0x70, 0x38, 0x41, 0x6c, 0x4a, 0x6e, 0x2f, 0x4a, 0x66, 0x45, 0x78, 0x38, 0x48, 0x6a, 0x74, + 0x53, 0x6a, 0x7a, 0x77, 0x42, 0x35, 0x52, 0x71, 0x56, 0x4f, 0x6b, 0x33, 0x6b, 0x72, 0x72, 0x44, + 0x71, 0x6e, 0x79, 0x31, 0x36, 0x41, 0x6d, 0x64, 0x78, 0x50, 0x34, 0x61, 0x56, 0x0a, 0x75, 0x68, + 0x6a, 0x67, 0x44, 0x62, 0x58, 0x4e, 0x66, 0x33, 0x31, 0x39, 0x63, 0x75, 0x43, 0x71, 0x32, 0x74, + 0x35, 0x68, 0x38, 0x31, 0x6e, 0x72, 0x48, 0x6d, 0x6a, 0x4b, 0x63, 0x6c, 0x55, 0x52, 0x59, 0x54, + 0x30, 0x2f, 0x6d, 0x64, 0x34, 0x43, 0x6b, 0x51, 0x6e, 0x64, 0x50, 0x51, 0x7a, 0x51, 0x33, 0x4c, + 0x61, 0x51, 0x73, 0x62, 0x38, 0x47, 0x4f, 0x63, 0x67, 0x35, 0x58, 0x45, 0x76, 0x67, 0x0a, 0x78, + 0x73, 0x68, 0x39, 0x65, 0x55, 0x58, 0x64, 0x75, 0x4f, 0x65, 0x45, 0x46, 0x6f, 0x72, 0x32, 0x54, + 0x6d, 0x73, 0x2f, 0x6b, 0x55, 0x62, 0x77, 0x76, 0x73, 0x66, 0x2b, 0x63, 0x30, 0x4f, 0x50, 0x58, + 0x53, 0x65, 0x70, 0x5a, 0x6b, 0x46, 0x35, 0x4b, 0x47, 0x51, 0x4d, 0x43, 0x50, 0x39, 0x36, 0x4b, + 0x32, 0x32, 0x4f, 0x43, 0x69, 0x43, 0x4b, 0x78, 0x58, 0x59, 0x37, 0x4b, 0x57, 0x56, 0x75, 0x0a, + 0x73, 0x6b, 0x47, 0x6a, 0x62, 0x70, 0x34, 0x65, 0x63, 0x58, 0x56, 0x57, 0x56, 0x47, 0x67, 0x4f, + 0x48, 0x6a, 0x4e, 0x51, 0x67, 0x73, 0x47, 0x75, 0x64, 0x45, 0x66, 0x75, 0x50, 0x63, 0x30, 0x49, + 0x71, 0x53, 0x42, 0x66, 0x6b, 0x46, 0x7a, 0x79, 0x71, 0x35, 0x63, 0x54, 0x36, 0x2b, 0x63, 0x6a, + 0x36, 0x31, 0x78, 0x73, 0x49, 0x76, 0x58, 0x53, 0x61, 0x35, 0x36, 0x78, 0x69, 0x69, 0x59, 0x51, + 0x0a, 0x39, 0x4b, 0x38, 0x2b, 0x61, 0x30, 0x75, 0x68, 0x58, 0x4d, 0x32, 0x66, 0x4f, 0x32, 0x49, + 0x57, 0x55, 0x78, 0x74, 0x2b, 0x70, 0x33, 0x35, 0x42, 0x73, 0x5a, 0x4d, 0x56, 0x44, 0x31, 0x7a, + 0x6f, 0x30, 0x67, 0x63, 0x6d, 0x31, 0x36, 0x6b, 0x73, 0x78, 0x77, 0x31, 0x36, 0x32, 0x73, 0x37, + 0x75, 0x61, 0x55, 0x74, 0x6a, 0x53, 0x56, 0x39, 0x61, 0x2f, 0x30, 0x58, 0x6d, 0x62, 0x65, 0x7a, + 0x45, 0x0a, 0x55, 0x53, 0x50, 0x36, 0x4c, 0x2f, 0x6a, 0x74, 0x57, 0x6a, 0x50, 0x50, 0x52, 0x52, + 0x33, 0x56, 0x57, 0x42, 0x70, 0x44, 0x34, 0x4a, 0x4d, 0x53, 0x61, 0x79, 0x77, 0x58, 0x67, 0x47, + 0x6b, 0x53, 0x34, 0x31, 0x69, 0x4e, 0x79, 0x68, 0x70, 0x50, 0x6f, 0x72, 0x35, 0x54, 0x6f, 0x69, + 0x34, 0x66, 0x4d, 0x41, 0x43, 0x49, 0x7a, 0x75, 0x34, 0x59, 0x4a, 0x59, 0x4b, 0x70, 0x69, 0x72, + 0x51, 0x52, 0x0a, 0x4f, 0x47, 0x71, 0x2b, 0x6e, 0x49, 0x54, 0x6e, 0x70, 0x6b, 0x75, 0x6a, 0x53, + 0x4e, 0x78, 0x34, 0x51, 0x4b, 0x66, 0x39, 0x49, 0x49, 0x4d, 0x4f, 0x4e, 0x6c, 0x36, 0x57, 0x33, + 0x52, 0x78, 0x31, 0x56, 0x4b, 0x6b, 0x2f, 0x76, 0x71, 0x50, 0x30, 0x59, 0x45, 0x4a, 0x64, 0x47, + 0x4a, 0x58, 0x44, 0x75, 0x70, 0x50, 0x41, 0x43, 0x49, 0x42, 0x77, 0x4e, 0x58, 0x38, 0x2f, 0x54, + 0x59, 0x78, 0x6b, 0x0a, 0x6c, 0x79, 0x34, 0x50, 0x71, 0x32, 0x43, 0x6e, 0x53, 0x31, 0x33, 0x39, + 0x6e, 0x59, 0x44, 0x31, 0x32, 0x4f, 0x50, 0x71, 0x32, 0x56, 0x41, 0x77, 0x47, 0x55, 0x7a, 0x56, + 0x6e, 0x72, 0x32, 0x32, 0x61, 0x74, 0x54, 0x73, 0x4e, 0x6a, 0x4d, 0x6a, 0x48, 0x4e, 0x79, 0x72, + 0x2f, 0x6b, 0x63, 0x6d, 0x34, 0x32, 0x4c, 0x72, 0x58, 0x5a, 0x65, 0x33, 0x79, 0x6a, 0x4c, 0x31, + 0x32, 0x58, 0x78, 0x2b, 0x0a, 0x5a, 0x46, 0x48, 0x74, 0x36, 0x77, 0x45, 0x71, 0x45, 0x33, 0x70, + 0x77, 0x5a, 0x66, 0x77, 0x46, 0x72, 0x4c, 0x75, 0x43, 0x38, 0x36, 0x48, 0x52, 0x73, 0x51, 0x7a, + 0x52, 0x4f, 0x4d, 0x46, 0x57, 0x34, 0x43, 0x32, 0x69, 0x4e, 0x76, 0x73, 0x56, 0x36, 0x48, 0x61, + 0x6e, 0x63, 0x34, 0x73, 0x70, 0x74, 0x56, 0x55, 0x6f, 0x58, 0x4a, 0x4b, 0x38, 0x74, 0x52, 0x68, + 0x39, 0x33, 0x70, 0x72, 0x67, 0x0a, 0x58, 0x47, 0x5a, 0x64, 0x64, 0x2f, 0x57, 0x58, 0x51, 0x70, + 0x64, 0x32, 0x6e, 0x76, 0x6f, 0x75, 0x76, 0x4d, 0x42, 0x70, 0x56, 0x6c, 0x6a, 0x63, 0x6d, 0x6a, + 0x4e, 0x47, 0x57, 0x56, 0x54, 0x72, 0x68, 0x54, 0x48, 0x75, 0x4a, 0x4d, 0x4f, 0x34, 0x6a, 0x56, + 0x44, 0x31, 0x34, 0x74, 0x73, 0x30, 0x36, 0x72, 0x37, 0x48, 0x46, 0x6c, 0x6d, 0x56, 0x47, 0x31, + 0x57, 0x50, 0x6c, 0x4c, 0x69, 0x44, 0x0a, 0x42, 0x6d, 0x41, 0x6d, 0x31, 0x68, 0x57, 0x64, 0x61, + 0x75, 0x38, 0x59, 0x52, 0x59, 0x4b, 0x50, 0x34, 0x4a, 0x38, 0x47, 0x57, 0x57, 0x52, 0x45, 0x34, + 0x35, 0x68, 0x64, 0x71, 0x52, 0x74, 0x7a, 0x43, 0x37, 0x51, 0x44, 0x65, 0x68, 0x65, 0x74, 0x78, + 0x62, 0x54, 0x67, 0x6a, 0x46, 0x6a, 0x64, 0x48, 0x4b, 0x34, 0x38, 0x57, 0x46, 0x71, 0x53, 0x2b, + 0x38, 0x6b, 0x5a, 0x53, 0x42, 0x63, 0x34, 0x0a, 0x2b, 0x4a, 0x6d, 0x4b, 0x56, 0x51, 0x46, 0x57, + 0x39, 0x79, 0x6d, 0x35, 0x32, 0x54, 0x54, 0x70, 0x61, 0x43, 0x5a, 0x57, 0x6b, 0x47, 0x71, 0x5a, + 0x6a, 0x30, 0x61, 0x47, 0x48, 0x54, 0x6e, 0x31, 0x63, 0x4f, 0x33, 0x6e, 0x4c, 0x65, 0x4f, 0x35, + 0x34, 0x44, 0x6f, 0x47, 0x6f, 0x76, 0x66, 0x70, 0x57, 0x38, 0x47, 0x64, 0x4c, 0x4d, 0x47, 0x70, + 0x5a, 0x59, 0x6b, 0x30, 0x48, 0x63, 0x76, 0x49, 0x0a, 0x78, 0x76, 0x4e, 0x70, 0x73, 0x2b, 0x58, + 0x54, 0x46, 0x55, 0x30, 0x50, 0x7a, 0x46, 0x6f, 0x55, 0x4d, 0x33, 0x54, 0x63, 0x73, 0x2b, 0x4f, + 0x66, 0x4b, 0x52, 0x6c, 0x61, 0x35, 0x62, 0x47, 0x4f, 0x31, 0x67, 0x48, 0x49, 0x2f, 0x5a, 0x79, + 0x39, 0x54, 0x78, 0x5a, 0x68, 0x6a, 0x35, 0x5a, 0x33, 0x6c, 0x75, 0x46, 0x42, 0x44, 0x58, 0x45, + 0x75, 0x34, 0x72, 0x56, 0x45, 0x6e, 0x4b, 0x34, 0x52, 0x0a, 0x41, 0x56, 0x35, 0x47, 0x4f, 0x45, + 0x72, 0x51, 0x49, 0x41, 0x6c, 0x70, 0x77, 0x76, 0x61, 0x64, 0x70, 0x52, 0x34, 0x73, 0x57, 0x31, + 0x30, 0x42, 0x72, 0x54, 0x2b, 0x50, 0x72, 0x4f, 0x44, 0x6c, 0x51, 0x36, 0x42, 0x6a, 0x4a, 0x71, + 0x75, 0x46, 0x4e, 0x46, 0x61, 0x5a, 0x31, 0x56, 0x35, 0x39, 0x78, 0x4f, 0x53, 0x30, 0x35, 0x39, + 0x6d, 0x6e, 0x35, 0x79, 0x79, 0x36, 0x31, 0x56, 0x71, 0x38, 0x0a, 0x39, 0x72, 0x54, 0x61, 0x33, + 0x78, 0x69, 0x78, 0x6c, 0x52, 0x47, 0x59, 0x46, 0x78, 0x45, 0x70, 0x4c, 0x65, 0x73, 0x4d, 0x59, + 0x66, 0x4a, 0x5a, 0x59, 0x41, 0x46, 0x39, 0x37, 0x35, 0x4e, 0x31, 0x68, 0x74, 0x71, 0x76, 0x53, + 0x4c, 0x6e, 0x49, 0x73, 0x70, 0x38, 0x36, 0x70, 0x74, 0x48, 0x59, 0x59, 0x63, 0x50, 0x74, 0x42, + 0x72, 0x4a, 0x4f, 0x34, 0x63, 0x53, 0x63, 0x4e, 0x79, 0x72, 0x6e, 0x0a, 0x49, 0x64, 0x53, 0x58, + 0x54, 0x58, 0x6d, 0x79, 0x4c, 0x33, 0x55, 0x43, 0x78, 0x56, 0x4e, 0x4b, 0x4f, 0x2f, 0x68, 0x73, + 0x6f, 0x65, 0x2f, 0x75, 0x4c, 0x32, 0x42, 0x61, 0x79, 0x68, 0x73, 0x45, 0x66, 0x4e, 0x7a, 0x63, + 0x34, 0x69, 0x55, 0x6c, 0x6b, 0x6c, 0x67, 0x30, 0x39, 0x6b, 0x2b, 0x44, 0x58, 0x51, 0x4f, 0x4e, + 0x50, 0x6b, 0x68, 0x61, 0x71, 0x52, 0x37, 0x34, 0x74, 0x75, 0x39, 0x47, 0x0a, 0x77, 0x55, 0x57, + 0x4f, 0x4d, 0x48, 0x68, 0x77, 0x6c, 0x32, 0x6e, 0x62, 0x35, 0x47, 0x65, 0x52, 0x64, 0x73, 0x39, + 0x76, 0x79, 0x39, 0x70, 0x63, 0x78, 0x63, 0x71, 0x38, 0x52, 0x6e, 0x67, 0x2b, 0x79, 0x46, 0x70, + 0x54, 0x46, 0x75, 0x56, 0x53, 0x64, 0x41, 0x43, 0x6e, 0x35, 0x75, 0x39, 0x62, 0x4d, 0x5a, 0x46, + 0x4f, 0x46, 0x6b, 0x64, 0x56, 0x75, 0x32, 0x6e, 0x36, 0x38, 0x42, 0x63, 0x65, 0x0a, 0x31, 0x4e, + 0x68, 0x75, 0x49, 0x31, 0x53, 0x48, 0x79, 0x6c, 0x42, 0x7a, 0x35, 0x30, 0x79, 0x4e, 0x6b, 0x43, + 0x4b, 0x4c, 0x33, 0x77, 0x51, 0x44, 0x47, 0x72, 0x38, 0x6b, 0x69, 0x2f, 0x54, 0x73, 0x75, 0x74, + 0x59, 0x30, 0x31, 0x48, 0x46, 0x30, 0x30, 0x76, 0x41, 0x36, 0x73, 0x4e, 0x75, 0x66, 0x4d, 0x66, + 0x6c, 0x6e, 0x61, 0x77, 0x79, 0x61, 0x67, 0x31, 0x4a, 0x69, 0x34, 0x46, 0x37, 0x6f, 0x0a, 0x41, + 0x4c, 0x49, 0x55, 0x39, 0x4e, 0x69, 0x47, 0x67, 0x41, 0x66, 0x6f, 0x33, 0x4a, 0x79, 0x4b, 0x52, + 0x6c, 0x56, 0x48, 0x6c, 0x71, 0x52, 0x2b, 0x63, 0x6b, 0x47, 0x74, 0x34, 0x6a, 0x66, 0x75, 0x51, + 0x59, 0x52, 0x5a, 0x4b, 0x46, 0x31, 0x34, 0x43, 0x51, 0x38, 0x66, 0x78, 0x65, 0x64, 0x62, 0x53, + 0x77, 0x44, 0x6d, 0x36, 0x33, 0x54, 0x77, 0x37, 0x58, 0x41, 0x49, 0x50, 0x43, 0x35, 0x39, 0x0a, + 0x4c, 0x32, 0x56, 0x49, 0x54, 0x45, 0x77, 0x46, 0x59, 0x51, 0x70, 0x6f, 0x4f, 0x77, 0x30, 0x4c, + 0x48, 0x45, 0x50, 0x78, 0x63, 0x53, 0x70, 0x36, 0x71, 0x4f, 0x53, 0x6a, 0x51, 0x76, 0x42, 0x4c, + 0x47, 0x6c, 0x68, 0x71, 0x4c, 0x46, 0x77, 0x38, 0x73, 0x4a, 0x50, 0x38, 0x69, 0x68, 0x59, 0x36, + 0x73, 0x6d, 0x41, 0x42, 0x53, 0x6d, 0x42, 0x76, 0x49, 0x45, 0x59, 0x4a, 0x5a, 0x79, 0x55, 0x35, + 0x0a, 0x56, 0x36, 0x47, 0x61, 0x31, 0x76, 0x4e, 0x62, 0x51, 0x43, 0x57, 0x67, 0x65, 0x43, 0x6f, + 0x71, 0x4b, 0x6f, 0x39, 0x5a, 0x5a, 0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, + 0x4e, 0x44, 0x20, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x20, 0x50, 0x52, 0x49, + 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +#define ROOT_CERT_DER_LENGTH 2000 +UA_Byte ROOT_CERT_DER_DATA[2000] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, + 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x46, + 0x6d, 0x54, 0x43, 0x43, 0x41, 0x34, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, + 0x44, 0x4f, 0x39, 0x78, 0x48, 0x76, 0x72, 0x67, 0x31, 0x4d, 0x48, 0x57, 0x74, 0x4e, 0x7a, 0x4c, + 0x49, 0x73, 0x30, 0x39, 0x35, 0x67, 0x58, 0x6b, 0x6d, 0x69, 0x4d, 0x77, 0x44, 0x51, 0x59, 0x4a, + 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x4c, 0x0a, 0x42, 0x51, 0x41, + 0x77, 0x5a, 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, + 0x43, 0x52, 0x45, 0x55, 0x78, 0x44, 0x6a, 0x41, 0x4d, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, + 0x4d, 0x42, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x51, 0x30, 0x77, 0x43, 0x77, 0x59, + 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x52, 0x44, 0x61, 0x58, 0x52, 0x35, 0x0a, 0x4d, 0x52, + 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x41, 0x78, 0x50, 0x63, 0x6d, + 0x64, 0x68, 0x62, 0x6d, 0x6c, 0x36, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x45, 0x44, + 0x41, 0x4f, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x73, 0x4d, 0x42, 0x30, 0x39, 0x79, 0x5a, 0x31, + 0x56, 0x75, 0x61, 0x58, 0x51, 0x78, 0x44, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, + 0x41, 0x4d, 0x4d, 0x42, 0x6c, 0x4a, 0x76, 0x62, 0x33, 0x52, 0x44, 0x51, 0x54, 0x41, 0x65, 0x46, + 0x77, 0x30, 0x79, 0x4e, 0x44, 0x41, 0x35, 0x4d, 0x54, 0x45, 0x78, 0x4d, 0x54, 0x55, 0x31, 0x4e, + 0x44, 0x64, 0x61, 0x46, 0x77, 0x30, 0x7a, 0x4e, 0x44, 0x41, 0x35, 0x4d, 0x44, 0x6b, 0x78, 0x4d, + 0x54, 0x55, 0x31, 0x4e, 0x44, 0x64, 0x61, 0x4d, 0x47, 0x59, 0x78, 0x43, 0x7a, 0x41, 0x4a, 0x0a, + 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6b, 0x52, 0x46, 0x4d, 0x51, 0x34, 0x77, + 0x44, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x56, 0x54, 0x64, 0x47, 0x46, 0x30, + 0x5a, 0x54, 0x45, 0x4e, 0x4d, 0x41, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x77, 0x77, 0x45, + 0x51, 0x32, 0x6c, 0x30, 0x65, 0x54, 0x45, 0x56, 0x4d, 0x42, 0x4d, 0x47, 0x41, 0x31, 0x55, 0x45, + 0x0a, 0x43, 0x67, 0x77, 0x4d, 0x54, 0x33, 0x4a, 0x6e, 0x59, 0x57, 0x35, 0x70, 0x65, 0x6d, 0x46, + 0x30, 0x61, 0x57, 0x39, 0x75, 0x4d, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, + 0x4c, 0x44, 0x41, 0x64, 0x50, 0x63, 0x6d, 0x64, 0x56, 0x62, 0x6d, 0x6c, 0x30, 0x4d, 0x51, 0x38, + 0x77, 0x44, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41, 0x5a, 0x53, 0x62, 0x32, 0x39, + 0x30, 0x0a, 0x51, 0x30, 0x45, 0x77, 0x67, 0x67, 0x49, 0x69, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, + 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, + 0x49, 0x43, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x49, 0x4b, 0x41, 0x6f, 0x49, 0x43, 0x41, 0x51, + 0x44, 0x4f, 0x78, 0x50, 0x54, 0x36, 0x4b, 0x6d, 0x52, 0x4e, 0x34, 0x51, 0x67, 0x4e, 0x55, 0x61, + 0x37, 0x54, 0x0a, 0x59, 0x2f, 0x56, 0x5a, 0x76, 0x68, 0x58, 0x6e, 0x53, 0x35, 0x75, 0x2f, 0x5a, + 0x47, 0x73, 0x37, 0x6d, 0x47, 0x37, 0x53, 0x4d, 0x6f, 0x50, 0x6f, 0x71, 0x49, 0x44, 0x44, 0x7a, + 0x4d, 0x74, 0x44, 0x57, 0x32, 0x66, 0x51, 0x78, 0x62, 0x34, 0x36, 0x48, 0x43, 0x76, 0x63, 0x38, + 0x55, 0x4f, 0x68, 0x38, 0x2f, 0x37, 0x34, 0x70, 0x50, 0x59, 0x48, 0x4c, 0x41, 0x34, 0x59, 0x58, + 0x67, 0x58, 0x37, 0x0a, 0x36, 0x49, 0x6f, 0x34, 0x6a, 0x52, 0x6b, 0x79, 0x6e, 0x6d, 0x50, 0x7a, + 0x44, 0x66, 0x43, 0x31, 0x37, 0x43, 0x56, 0x4c, 0x53, 0x63, 0x64, 0x42, 0x58, 0x35, 0x51, 0x48, + 0x57, 0x43, 0x6c, 0x5a, 0x56, 0x48, 0x43, 0x58, 0x77, 0x4c, 0x75, 0x42, 0x45, 0x59, 0x49, 0x47, + 0x6f, 0x30, 0x78, 0x33, 0x65, 0x66, 0x75, 0x39, 0x6c, 0x75, 0x69, 0x73, 0x70, 0x70, 0x73, 0x4c, + 0x7a, 0x59, 0x54, 0x4d, 0x0a, 0x38, 0x31, 0x62, 0x79, 0x6a, 0x2b, 0x78, 0x74, 0x49, 0x64, 0x42, + 0x72, 0x68, 0x4c, 0x68, 0x39, 0x48, 0x5a, 0x4f, 0x73, 0x57, 0x6b, 0x63, 0x70, 0x79, 0x68, 0x38, + 0x75, 0x52, 0x55, 0x6d, 0x35, 0x43, 0x50, 0x76, 0x2f, 0x74, 0x78, 0x4f, 0x36, 0x4f, 0x6a, 0x6e, + 0x41, 0x67, 0x4f, 0x2b, 0x47, 0x33, 0x38, 0x38, 0x56, 0x71, 0x55, 0x4b, 0x59, 0x38, 0x76, 0x54, + 0x46, 0x54, 0x30, 0x49, 0x61, 0x0a, 0x76, 0x36, 0x4d, 0x36, 0x6b, 0x62, 0x57, 0x45, 0x78, 0x49, + 0x50, 0x5a, 0x52, 0x62, 0x6d, 0x51, 0x52, 0x64, 0x74, 0x5a, 0x74, 0x59, 0x57, 0x72, 0x54, 0x43, + 0x2f, 0x50, 0x54, 0x43, 0x45, 0x6b, 0x73, 0x34, 0x61, 0x76, 0x6e, 0x47, 0x38, 0x44, 0x61, 0x52, + 0x4f, 0x39, 0x66, 0x42, 0x6c, 0x79, 0x65, 0x37, 0x61, 0x32, 0x45, 0x6f, 0x62, 0x35, 0x33, 0x34, + 0x42, 0x76, 0x4d, 0x2f, 0x74, 0x76, 0x0a, 0x30, 0x74, 0x63, 0x6f, 0x38, 0x2b, 0x50, 0x69, 0x58, + 0x52, 0x70, 0x61, 0x6a, 0x66, 0x71, 0x56, 0x68, 0x31, 0x43, 0x70, 0x61, 0x68, 0x7a, 0x7a, 0x78, + 0x5a, 0x35, 0x65, 0x76, 0x4d, 0x7a, 0x77, 0x78, 0x4d, 0x43, 0x2f, 0x74, 0x75, 0x61, 0x69, 0x54, + 0x76, 0x76, 0x4d, 0x56, 0x44, 0x62, 0x33, 0x63, 0x68, 0x53, 0x77, 0x41, 0x4a, 0x55, 0x6c, 0x75, + 0x33, 0x48, 0x73, 0x59, 0x35, 0x5a, 0x4d, 0x0a, 0x72, 0x52, 0x59, 0x31, 0x6b, 0x56, 0x30, 0x4a, + 0x74, 0x4f, 0x35, 0x68, 0x64, 0x58, 0x44, 0x57, 0x61, 0x79, 0x35, 0x59, 0x52, 0x78, 0x75, 0x42, + 0x2f, 0x76, 0x45, 0x65, 0x2f, 0x36, 0x77, 0x2b, 0x4b, 0x4e, 0x42, 0x35, 0x75, 0x4e, 0x62, 0x73, + 0x55, 0x78, 0x6f, 0x6a, 0x35, 0x79, 0x48, 0x44, 0x6b, 0x45, 0x67, 0x75, 0x42, 0x4b, 0x4a, 0x38, + 0x59, 0x77, 0x42, 0x36, 0x44, 0x47, 0x4e, 0x31, 0x0a, 0x32, 0x53, 0x57, 0x57, 0x5a, 0x45, 0x47, + 0x34, 0x38, 0x4b, 0x67, 0x30, 0x6e, 0x52, 0x68, 0x6b, 0x54, 0x35, 0x6d, 0x62, 0x45, 0x44, 0x45, + 0x68, 0x49, 0x57, 0x43, 0x2f, 0x61, 0x30, 0x50, 0x6e, 0x73, 0x6a, 0x49, 0x71, 0x69, 0x49, 0x68, + 0x6a, 0x5a, 0x6a, 0x61, 0x77, 0x35, 0x6f, 0x62, 0x74, 0x30, 0x38, 0x71, 0x58, 0x2b, 0x63, 0x79, + 0x67, 0x32, 0x52, 0x31, 0x4e, 0x66, 0x51, 0x77, 0x7a, 0x0a, 0x74, 0x35, 0x33, 0x68, 0x79, 0x47, + 0x6c, 0x48, 0x65, 0x35, 0x4e, 0x35, 0x61, 0x61, 0x7a, 0x77, 0x57, 0x4b, 0x4a, 0x42, 0x73, 0x72, + 0x78, 0x48, 0x50, 0x74, 0x77, 0x38, 0x79, 0x48, 0x56, 0x64, 0x4a, 0x64, 0x73, 0x66, 0x59, 0x6c, + 0x38, 0x70, 0x7a, 0x39, 0x63, 0x34, 0x76, 0x54, 0x50, 0x59, 0x6e, 0x5a, 0x33, 0x4d, 0x41, 0x41, + 0x46, 0x59, 0x44, 0x76, 0x57, 0x70, 0x33, 0x45, 0x52, 0x44, 0x0a, 0x30, 0x70, 0x48, 0x48, 0x57, + 0x6d, 0x67, 0x30, 0x73, 0x6c, 0x76, 0x41, 0x66, 0x4f, 0x6e, 0x6f, 0x35, 0x31, 0x55, 0x41, 0x32, + 0x53, 0x65, 0x77, 0x2b, 0x51, 0x52, 0x37, 0x53, 0x53, 0x30, 0x33, 0x70, 0x49, 0x55, 0x69, 0x58, + 0x53, 0x68, 0x75, 0x2b, 0x38, 0x51, 0x56, 0x66, 0x6b, 0x6f, 0x6b, 0x66, 0x4a, 0x66, 0x67, 0x71, + 0x30, 0x4f, 0x45, 0x30, 0x33, 0x31, 0x78, 0x46, 0x77, 0x66, 0x41, 0x0a, 0x5a, 0x46, 0x68, 0x39, + 0x53, 0x49, 0x4b, 0x48, 0x38, 0x51, 0x31, 0x32, 0x47, 0x55, 0x61, 0x6c, 0x34, 0x53, 0x55, 0x73, + 0x65, 0x4d, 0x4d, 0x43, 0x34, 0x73, 0x76, 0x55, 0x4f, 0x48, 0x4d, 0x36, 0x6d, 0x58, 0x2b, 0x32, + 0x4f, 0x64, 0x5a, 0x33, 0x64, 0x32, 0x77, 0x79, 0x4c, 0x77, 0x55, 0x34, 0x43, 0x37, 0x6a, 0x2b, + 0x32, 0x6e, 0x71, 0x51, 0x66, 0x53, 0x39, 0x45, 0x4f, 0x63, 0x65, 0x66, 0x0a, 0x42, 0x58, 0x76, + 0x53, 0x4e, 0x59, 0x33, 0x71, 0x2f, 0x36, 0x61, 0x34, 0x37, 0x48, 0x49, 0x47, 0x5a, 0x4d, 0x62, + 0x6b, 0x4a, 0x75, 0x35, 0x7a, 0x65, 0x51, 0x49, 0x44, 0x41, 0x51, 0x41, 0x42, 0x6f, 0x7a, 0x38, + 0x77, 0x50, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x52, 0x4d, 0x42, 0x41, 0x66, 0x38, + 0x45, 0x42, 0x54, 0x41, 0x44, 0x41, 0x51, 0x48, 0x2f, 0x4d, 0x41, 0x73, 0x47, 0x0a, 0x41, 0x31, + 0x55, 0x64, 0x44, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49, 0x42, 0x42, 0x6a, 0x41, 0x64, 0x42, 0x67, + 0x4e, 0x56, 0x48, 0x51, 0x34, 0x45, 0x46, 0x67, 0x51, 0x55, 0x30, 0x6c, 0x76, 0x57, 0x4b, 0x57, + 0x53, 0x77, 0x72, 0x4c, 0x51, 0x74, 0x44, 0x30, 0x2f, 0x64, 0x76, 0x57, 0x56, 0x5a, 0x67, 0x73, + 0x64, 0x42, 0x39, 0x43, 0x59, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x0a, 0x68, + 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x4c, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, + 0x42, 0x44, 0x44, 0x68, 0x4b, 0x76, 0x57, 0x30, 0x73, 0x55, 0x70, 0x64, 0x75, 0x49, 0x47, 0x74, + 0x68, 0x4e, 0x34, 0x6f, 0x38, 0x62, 0x37, 0x61, 0x45, 0x41, 0x6e, 0x4e, 0x77, 0x2f, 0x2b, 0x62, + 0x61, 0x5a, 0x30, 0x54, 0x38, 0x32, 0x6e, 0x59, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x50, 0x76, 0x0a, + 0x42, 0x76, 0x30, 0x4e, 0x48, 0x50, 0x6a, 0x53, 0x5a, 0x37, 0x33, 0x4d, 0x43, 0x56, 0x6c, 0x4d, + 0x61, 0x2b, 0x66, 0x39, 0x65, 0x62, 0x71, 0x65, 0x73, 0x54, 0x49, 0x45, 0x77, 0x47, 0x41, 0x65, + 0x78, 0x4a, 0x45, 0x39, 0x76, 0x4b, 0x49, 0x5a, 0x68, 0x31, 0x30, 0x53, 0x70, 0x79, 0x78, 0x61, + 0x62, 0x77, 0x68, 0x56, 0x6f, 0x47, 0x41, 0x71, 0x30, 0x74, 0x44, 0x51, 0x68, 0x7a, 0x47, 0x77, + 0x0a, 0x71, 0x6d, 0x34, 0x4d, 0x30, 0x34, 0x4c, 0x62, 0x33, 0x53, 0x46, 0x42, 0x75, 0x76, 0x52, + 0x70, 0x46, 0x34, 0x6f, 0x68, 0x62, 0x4d, 0x51, 0x64, 0x47, 0x49, 0x76, 0x71, 0x2b, 0x75, 0x34, + 0x72, 0x6d, 0x6d, 0x39, 0x54, 0x62, 0x69, 0x70, 0x41, 0x63, 0x43, 0x33, 0x47, 0x37, 0x50, 0x32, + 0x6a, 0x4c, 0x42, 0x53, 0x38, 0x37, 0x55, 0x48, 0x7a, 0x32, 0x74, 0x71, 0x42, 0x74, 0x4b, 0x64, + 0x4d, 0x0a, 0x64, 0x39, 0x44, 0x47, 0x73, 0x78, 0x78, 0x7a, 0x6b, 0x50, 0x75, 0x4c, 0x77, 0x48, + 0x50, 0x52, 0x36, 0x58, 0x75, 0x77, 0x75, 0x30, 0x78, 0x35, 0x5a, 0x38, 0x37, 0x4f, 0x58, 0x6e, + 0x6e, 0x6e, 0x6a, 0x38, 0x75, 0x59, 0x77, 0x61, 0x31, 0x2b, 0x55, 0x56, 0x6f, 0x65, 0x59, 0x7a, + 0x4a, 0x4c, 0x30, 0x75, 0x31, 0x51, 0x38, 0x46, 0x2f, 0x6c, 0x47, 0x63, 0x7a, 0x39, 0x65, 0x57, + 0x44, 0x6d, 0x0a, 0x6e, 0x58, 0x78, 0x75, 0x36, 0x64, 0x35, 0x79, 0x68, 0x70, 0x6c, 0x64, 0x4a, + 0x6f, 0x2b, 0x67, 0x42, 0x71, 0x72, 0x4d, 0x58, 0x6c, 0x32, 0x58, 0x4e, 0x4e, 0x5a, 0x61, 0x39, + 0x6e, 0x4d, 0x4a, 0x52, 0x54, 0x64, 0x2b, 0x6f, 0x57, 0x69, 0x54, 0x47, 0x65, 0x4e, 0x74, 0x4e, + 0x48, 0x6f, 0x41, 0x44, 0x7a, 0x34, 0x30, 0x2b, 0x41, 0x64, 0x62, 0x69, 0x47, 0x35, 0x48, 0x35, + 0x35, 0x30, 0x77, 0x0a, 0x4d, 0x45, 0x54, 0x57, 0x64, 0x54, 0x4e, 0x63, 0x4d, 0x6d, 0x4c, 0x31, + 0x77, 0x57, 0x6a, 0x30, 0x67, 0x35, 0x35, 0x49, 0x57, 0x7a, 0x65, 0x65, 0x48, 0x68, 0x73, 0x4e, + 0x54, 0x75, 0x66, 0x46, 0x55, 0x70, 0x48, 0x44, 0x4d, 0x34, 0x33, 0x61, 0x2f, 0x33, 0x7a, 0x53, + 0x48, 0x6e, 0x41, 0x44, 0x6f, 0x75, 0x5a, 0x78, 0x6e, 0x53, 0x67, 0x72, 0x71, 0x30, 0x31, 0x76, + 0x55, 0x75, 0x69, 0x70, 0x0a, 0x31, 0x6b, 0x45, 0x72, 0x35, 0x65, 0x53, 0x59, 0x64, 0x47, 0x6f, + 0x64, 0x34, 0x36, 0x78, 0x58, 0x35, 0x30, 0x56, 0x56, 0x4c, 0x79, 0x61, 0x53, 0x72, 0x39, 0x2b, + 0x37, 0x71, 0x4a, 0x64, 0x75, 0x77, 0x2b, 0x7a, 0x73, 0x41, 0x6d, 0x67, 0x50, 0x55, 0x58, 0x65, + 0x58, 0x7a, 0x79, 0x31, 0x7a, 0x44, 0x34, 0x46, 0x47, 0x61, 0x54, 0x2f, 0x56, 0x62, 0x57, 0x63, + 0x70, 0x37, 0x76, 0x65, 0x4c, 0x0a, 0x56, 0x48, 0x58, 0x53, 0x38, 0x35, 0x6b, 0x72, 0x72, 0x5a, + 0x6c, 0x4f, 0x64, 0x6c, 0x4b, 0x56, 0x4a, 0x6d, 0x45, 0x78, 0x4a, 0x45, 0x30, 0x6e, 0x4c, 0x4d, + 0x6b, 0x38, 0x55, 0x50, 0x53, 0x63, 0x75, 0x46, 0x35, 0x4c, 0x48, 0x36, 0x69, 0x61, 0x39, 0x51, + 0x67, 0x41, 0x53, 0x34, 0x6d, 0x35, 0x43, 0x66, 0x55, 0x33, 0x76, 0x69, 0x35, 0x77, 0x6d, 0x37, + 0x71, 0x6e, 0x59, 0x56, 0x77, 0x37, 0x0a, 0x45, 0x55, 0x4e, 0x50, 0x39, 0x36, 0x72, 0x78, 0x31, + 0x44, 0x66, 0x64, 0x2f, 0x41, 0x58, 0x73, 0x6a, 0x4a, 0x44, 0x62, 0x50, 0x6e, 0x4a, 0x57, 0x53, + 0x45, 0x69, 0x73, 0x4e, 0x35, 0x63, 0x31, 0x64, 0x67, 0x30, 0x56, 0x74, 0x48, 0x51, 0x56, 0x70, + 0x33, 0x67, 0x77, 0x39, 0x52, 0x56, 0x4e, 0x74, 0x66, 0x6d, 0x2b, 0x59, 0x2b, 0x31, 0x72, 0x33, + 0x2f, 0x44, 0x61, 0x44, 0x42, 0x48, 0x54, 0x0a, 0x49, 0x65, 0x33, 0x30, 0x79, 0x51, 0x50, 0x6c, + 0x41, 0x56, 0x72, 0x56, 0x6a, 0x57, 0x44, 0x77, 0x6e, 0x48, 0x73, 0x35, 0x31, 0x34, 0x50, 0x47, + 0x75, 0x69, 0x4d, 0x42, 0x51, 0x42, 0x67, 0x61, 0x6a, 0x67, 0x6e, 0x64, 0x4f, 0x45, 0x70, 0x54, + 0x67, 0x5a, 0x56, 0x48, 0x2f, 0x46, 0x33, 0x6a, 0x34, 0x59, 0x39, 0x6b, 0x37, 0x36, 0x4c, 0x44, + 0x62, 0x35, 0x45, 0x49, 0x54, 0x68, 0x51, 0x59, 0x0a, 0x59, 0x53, 0x63, 0x33, 0x31, 0x5a, 0x41, + 0x6b, 0x63, 0x49, 0x65, 0x79, 0x53, 0x66, 0x6f, 0x33, 0x2b, 0x51, 0x39, 0x4a, 0x69, 0x78, 0x59, + 0x51, 0x42, 0x78, 0x2f, 0x78, 0x4a, 0x57, 0x34, 0x4d, 0x37, 0x6a, 0x51, 0x33, 0x79, 0x6d, 0x42, + 0x65, 0x58, 0x59, 0x6d, 0x67, 0x66, 0x49, 0x76, 0x2b, 0x2f, 0x51, 0x53, 0x32, 0x59, 0x34, 0x4d, + 0x6d, 0x53, 0x63, 0x6b, 0x50, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, + 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +/* Contains the intermediateCA certificate */ +#define ROOT_CRL_PEM_LENGTH 1109 +UA_Byte ROOT_CRL_PEM_DATA[1109] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x58, 0x35, 0x30, 0x39, 0x20, + 0x43, 0x52, 0x4c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x43, 0x6a, 0x43, + 0x42, 0x38, 0x77, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, + 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x6d, 0x4d, 0x51, 0x73, + 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x45, 0x52, 0x54, 0x45, + 0x4f, 0x4d, 0x41, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0a, 0x43, 0x41, 0x77, 0x46, 0x55, 0x33, + 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x44, 0x54, 0x41, 0x4c, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, + 0x63, 0x4d, 0x42, 0x45, 0x4e, 0x70, 0x64, 0x48, 0x6b, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, + 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x44, 0x45, 0x39, 0x79, 0x5a, 0x32, 0x46, 0x75, 0x61, 0x58, + 0x70, 0x68, 0x64, 0x47, 0x6c, 0x76, 0x62, 0x6a, 0x45, 0x51, 0x0a, 0x4d, 0x41, 0x34, 0x47, 0x41, + 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x48, 0x54, 0x33, 0x4a, 0x6e, 0x56, 0x57, 0x35, 0x70, 0x64, + 0x44, 0x45, 0x50, 0x4d, 0x41, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x47, 0x55, + 0x6d, 0x39, 0x76, 0x64, 0x45, 0x4e, 0x42, 0x46, 0x77, 0x30, 0x79, 0x4e, 0x44, 0x41, 0x35, 0x4d, + 0x54, 0x45, 0x78, 0x4d, 0x6a, 0x41, 0x77, 0x4d, 0x6a, 0x42, 0x61, 0x0a, 0x46, 0x77, 0x30, 0x79, + 0x4e, 0x44, 0x45, 0x77, 0x4d, 0x54, 0x45, 0x78, 0x4d, 0x6a, 0x41, 0x77, 0x4d, 0x6a, 0x42, 0x61, + 0x4d, 0x43, 0x63, 0x77, 0x4a, 0x51, 0x49, 0x55, 0x54, 0x32, 0x55, 0x75, 0x68, 0x65, 0x71, 0x72, + 0x77, 0x30, 0x34, 0x50, 0x76, 0x54, 0x56, 0x79, 0x32, 0x73, 0x46, 0x44, 0x4e, 0x56, 0x4e, 0x38, + 0x5a, 0x30, 0x63, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x44, 0x6b, 0x78, 0x0a, 0x4d, 0x54, 0x45, + 0x79, 0x4d, 0x44, 0x41, 0x77, 0x4f, 0x56, 0x71, 0x67, 0x4d, 0x44, 0x41, 0x75, 0x4d, 0x42, 0x38, + 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4d, 0x42, 0x61, 0x41, 0x46, 0x4e, 0x4a, + 0x62, 0x31, 0x69, 0x6c, 0x6b, 0x73, 0x4b, 0x79, 0x30, 0x4c, 0x51, 0x39, 0x50, 0x33, 0x62, 0x31, + 0x6c, 0x57, 0x59, 0x4c, 0x48, 0x51, 0x66, 0x51, 0x6d, 0x4d, 0x41, 0x73, 0x47, 0x0a, 0x41, 0x31, + 0x55, 0x64, 0x46, 0x41, 0x51, 0x45, 0x41, 0x67, 0x49, 0x51, 0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, + 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, + 0x4f, 0x43, 0x41, 0x67, 0x45, 0x41, 0x59, 0x30, 0x58, 0x6c, 0x44, 0x31, 0x34, 0x4b, 0x71, 0x32, + 0x51, 0x41, 0x70, 0x77, 0x61, 0x70, 0x68, 0x56, 0x53, 0x58, 0x4b, 0x33, 0x53, 0x39, 0x0a, 0x55, + 0x58, 0x7a, 0x57, 0x41, 0x48, 0x2b, 0x2f, 0x68, 0x39, 0x61, 0x38, 0x46, 0x58, 0x2b, 0x65, 0x45, + 0x61, 0x6f, 0x68, 0x6f, 0x6a, 0x47, 0x51, 0x36, 0x62, 0x57, 0x34, 0x72, 0x68, 0x42, 0x4e, 0x5a, + 0x75, 0x4f, 0x2b, 0x57, 0x31, 0x38, 0x79, 0x78, 0x6b, 0x47, 0x33, 0x2f, 0x61, 0x55, 0x75, 0x68, + 0x30, 0x58, 0x65, 0x77, 0x58, 0x4a, 0x6f, 0x46, 0x67, 0x39, 0x4a, 0x2f, 0x6e, 0x51, 0x6c, 0x0a, + 0x6a, 0x67, 0x5a, 0x70, 0x70, 0x46, 0x6f, 0x54, 0x6b, 0x4a, 0x6d, 0x49, 0x53, 0x64, 0x2f, 0x75, + 0x34, 0x65, 0x70, 0x4b, 0x6b, 0x31, 0x63, 0x4d, 0x2f, 0x71, 0x33, 0x32, 0x6e, 0x42, 0x63, 0x70, + 0x58, 0x7a, 0x6a, 0x6f, 0x5a, 0x33, 0x66, 0x57, 0x6a, 0x43, 0x37, 0x55, 0x5a, 0x4b, 0x62, 0x46, + 0x32, 0x63, 0x31, 0x43, 0x4e, 0x53, 0x61, 0x44, 0x6a, 0x64, 0x35, 0x65, 0x59, 0x2b, 0x36, 0x53, + 0x0a, 0x59, 0x6c, 0x4b, 0x36, 0x45, 0x47, 0x66, 0x6b, 0x57, 0x58, 0x74, 0x66, 0x30, 0x68, 0x50, + 0x46, 0x42, 0x4f, 0x39, 0x69, 0x69, 0x65, 0x32, 0x33, 0x68, 0x41, 0x71, 0x58, 0x4a, 0x6e, 0x67, + 0x46, 0x56, 0x75, 0x67, 0x50, 0x53, 0x39, 0x78, 0x68, 0x38, 0x6d, 0x47, 0x53, 0x64, 0x39, 0x6e, + 0x4d, 0x32, 0x6e, 0x50, 0x68, 0x46, 0x43, 0x49, 0x67, 0x50, 0x6a, 0x37, 0x41, 0x32, 0x73, 0x58, + 0x76, 0x0a, 0x78, 0x79, 0x33, 0x37, 0x36, 0x48, 0x67, 0x6b, 0x2b, 0x66, 0x73, 0x55, 0x59, 0x39, + 0x51, 0x6d, 0x66, 0x42, 0x41, 0x55, 0x46, 0x6e, 0x6c, 0x2b, 0x2b, 0x36, 0x79, 0x6c, 0x54, 0x39, + 0x6c, 0x4d, 0x4e, 0x62, 0x78, 0x2b, 0x50, 0x5a, 0x73, 0x33, 0x30, 0x78, 0x78, 0x64, 0x48, 0x6d, + 0x4f, 0x6f, 0x61, 0x38, 0x69, 0x4a, 0x73, 0x46, 0x56, 0x4a, 0x67, 0x34, 0x71, 0x4c, 0x33, 0x31, + 0x39, 0x6a, 0x0a, 0x55, 0x63, 0x4b, 0x49, 0x67, 0x41, 0x6e, 0x56, 0x48, 0x6e, 0x41, 0x4a, 0x32, + 0x59, 0x42, 0x61, 0x30, 0x4a, 0x30, 0x56, 0x79, 0x38, 0x33, 0x38, 0x30, 0x77, 0x48, 0x64, 0x43, + 0x54, 0x50, 0x5a, 0x32, 0x43, 0x74, 0x77, 0x2f, 0x76, 0x62, 0x74, 0x75, 0x54, 0x56, 0x54, 0x4b, + 0x36, 0x62, 0x44, 0x4b, 0x37, 0x72, 0x76, 0x6a, 0x58, 0x58, 0x4c, 0x34, 0x7a, 0x56, 0x66, 0x71, + 0x7a, 0x32, 0x78, 0x0a, 0x30, 0x63, 0x6e, 0x66, 0x70, 0x64, 0x55, 0x49, 0x57, 0x37, 0x4a, 0x36, + 0x68, 0x64, 0x4e, 0x70, 0x58, 0x77, 0x33, 0x76, 0x4c, 0x67, 0x4c, 0x66, 0x76, 0x57, 0x6b, 0x59, + 0x4b, 0x65, 0x79, 0x35, 0x61, 0x79, 0x72, 0x7a, 0x36, 0x32, 0x37, 0x45, 0x4c, 0x32, 0x47, 0x36, + 0x65, 0x77, 0x51, 0x53, 0x78, 0x71, 0x71, 0x53, 0x4c, 0x73, 0x6b, 0x67, 0x52, 0x52, 0x55, 0x74, + 0x6a, 0x4e, 0x66, 0x79, 0x0a, 0x38, 0x2b, 0x71, 0x34, 0x47, 0x49, 0x32, 0x71, 0x47, 0x4e, 0x71, + 0x4d, 0x48, 0x75, 0x79, 0x32, 0x39, 0x53, 0x70, 0x31, 0x74, 0x4c, 0x78, 0x76, 0x73, 0x71, 0x56, + 0x6e, 0x30, 0x52, 0x55, 0x58, 0x46, 0x42, 0x44, 0x69, 0x62, 0x6c, 0x31, 0x5a, 0x74, 0x67, 0x4f, + 0x65, 0x2b, 0x33, 0x2f, 0x4c, 0x2f, 0x58, 0x7a, 0x6a, 0x76, 0x73, 0x45, 0x78, 0x66, 0x73, 0x77, + 0x4e, 0x54, 0x73, 0x50, 0x4f, 0x0a, 0x2b, 0x54, 0x49, 0x69, 0x42, 0x55, 0x71, 0x5a, 0x4a, 0x4a, + 0x4c, 0x78, 0x61, 0x6d, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x53, 0x45, 0x4d, 0x4e, 0x67, 0x6a, 0x69, + 0x77, 0x75, 0x33, 0x62, 0x45, 0x79, 0x4e, 0x65, 0x6d, 0x63, 0x6b, 0x6c, 0x31, 0x74, 0x70, 0x64, + 0x6a, 0x67, 0x36, 0x2b, 0x79, 0x36, 0x68, 0x56, 0x71, 0x6b, 0x74, 0x76, 0x65, 0x37, 0x4a, 0x42, + 0x33, 0x45, 0x64, 0x67, 0x4f, 0x4c, 0x0a, 0x45, 0x4c, 0x68, 0x7a, 0x50, 0x41, 0x54, 0x38, 0x48, + 0x52, 0x61, 0x75, 0x43, 0x6b, 0x71, 0x47, 0x41, 0x67, 0x61, 0x57, 0x62, 0x58, 0x43, 0x38, 0x31, + 0x65, 0x6d, 0x56, 0x55, 0x52, 0x51, 0x4e, 0x42, 0x71, 0x74, 0x55, 0x30, 0x30, 0x75, 0x77, 0x4a, + 0x45, 0x75, 0x4c, 0x35, 0x73, 0x47, 0x32, 0x4c, 0x4c, 0x53, 0x43, 0x50, 0x2f, 0x78, 0x30, 0x52, + 0x76, 0x46, 0x63, 0x73, 0x32, 0x79, 0x68, 0x0a, 0x73, 0x4a, 0x6f, 0x59, 0x4d, 0x31, 0x61, 0x6f, + 0x6c, 0x43, 0x52, 0x2f, 0x32, 0x52, 0x33, 0x2f, 0x72, 0x2b, 0x57, 0x39, 0x55, 0x52, 0x39, 0x37, + 0x59, 0x72, 0x59, 0x74, 0x75, 0x4a, 0x62, 0x6a, 0x52, 0x42, 0x71, 0x69, 0x56, 0x4d, 0x49, 0x52, + 0x70, 0x53, 0x2f, 0x49, 0x62, 0x49, 0x77, 0x72, 0x50, 0x72, 0x5a, 0x45, 0x47, 0x75, 0x58, 0x67, + 0x35, 0x44, 0x48, 0x56, 0x33, 0x6e, 0x36, 0x63, 0x0a, 0x66, 0x6d, 0x58, 0x2f, 0x76, 0x4b, 0x45, + 0x62, 0x6d, 0x72, 0x74, 0x49, 0x6c, 0x57, 0x6a, 0x45, 0x36, 0x67, 0x49, 0x3d, 0x0a, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x58, 0x35, 0x30, 0x39, 0x20, 0x43, 0x52, 0x4c, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +#define ROOT_EMPTY_CRL_PEM_LENGTH 1052 +UA_Byte ROOT_EMPTY_CRL_PEM_DATA[1052] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x58, 0x35, 0x30, 0x39, 0x20, + 0x43, 0x52, 0x4c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x34, 0x54, 0x43, + 0x42, 0x79, 0x67, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, + 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x6d, 0x4d, 0x51, 0x73, + 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x45, 0x52, 0x54, 0x45, + 0x4f, 0x4d, 0x41, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0a, 0x43, 0x41, 0x77, 0x46, 0x55, 0x33, + 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x44, 0x54, 0x41, 0x4c, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, + 0x63, 0x4d, 0x42, 0x45, 0x4e, 0x70, 0x64, 0x48, 0x6b, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, + 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x44, 0x45, 0x39, 0x79, 0x5a, 0x32, 0x46, 0x75, 0x61, 0x58, + 0x70, 0x68, 0x64, 0x47, 0x6c, 0x76, 0x62, 0x6a, 0x45, 0x51, 0x0a, 0x4d, 0x41, 0x34, 0x47, 0x41, + 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x48, 0x54, 0x33, 0x4a, 0x6e, 0x56, 0x57, 0x35, 0x70, 0x64, + 0x44, 0x45, 0x50, 0x4d, 0x41, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x47, 0x55, + 0x6d, 0x39, 0x76, 0x64, 0x45, 0x4e, 0x42, 0x46, 0x77, 0x30, 0x79, 0x4e, 0x44, 0x41, 0x35, 0x4d, + 0x54, 0x45, 0x78, 0x4d, 0x6a, 0x41, 0x30, 0x4e, 0x44, 0x56, 0x61, 0x0a, 0x46, 0x77, 0x30, 0x79, + 0x4e, 0x44, 0x45, 0x77, 0x4d, 0x54, 0x45, 0x78, 0x4d, 0x6a, 0x41, 0x30, 0x4e, 0x44, 0x56, 0x61, + 0x6f, 0x44, 0x41, 0x77, 0x4c, 0x6a, 0x41, 0x66, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x53, 0x4d, 0x45, + 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x54, 0x53, 0x57, 0x39, 0x59, 0x70, 0x5a, 0x4c, 0x43, 0x73, + 0x74, 0x43, 0x30, 0x50, 0x54, 0x39, 0x32, 0x39, 0x5a, 0x56, 0x6d, 0x43, 0x0a, 0x78, 0x30, 0x48, + 0x30, 0x4a, 0x6a, 0x41, 0x4c, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x52, 0x51, 0x45, 0x42, 0x41, 0x49, + 0x43, 0x45, 0x41, 0x4d, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, + 0x4e, 0x41, 0x51, 0x45, 0x4c, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x42, 0x41, 0x42, 0x59, + 0x65, 0x48, 0x74, 0x57, 0x61, 0x5a, 0x33, 0x6b, 0x4c, 0x46, 0x45, 0x30, 0x63, 0x0a, 0x77, 0x66, + 0x66, 0x42, 0x4b, 0x37, 0x32, 0x62, 0x50, 0x48, 0x6c, 0x6f, 0x34, 0x31, 0x79, 0x2f, 0x6d, 0x48, + 0x38, 0x65, 0x52, 0x63, 0x47, 0x66, 0x57, 0x46, 0x6a, 0x45, 0x6d, 0x50, 0x58, 0x49, 0x67, 0x36, + 0x71, 0x31, 0x44, 0x79, 0x37, 0x66, 0x54, 0x6f, 0x54, 0x69, 0x44, 0x71, 0x72, 0x52, 0x6e, 0x49, + 0x41, 0x68, 0x53, 0x44, 0x6e, 0x4c, 0x6a, 0x56, 0x64, 0x4f, 0x34, 0x74, 0x52, 0x66, 0x0a, 0x73, + 0x6a, 0x64, 0x72, 0x58, 0x2f, 0x32, 0x67, 0x52, 0x30, 0x4e, 0x6f, 0x57, 0x66, 0x48, 0x63, 0x78, + 0x58, 0x61, 0x6b, 0x41, 0x42, 0x4e, 0x31, 0x51, 0x35, 0x45, 0x4e, 0x39, 0x61, 0x4f, 0x74, 0x35, + 0x45, 0x2b, 0x6d, 0x4d, 0x4b, 0x46, 0x59, 0x46, 0x74, 0x4a, 0x55, 0x50, 0x79, 0x76, 0x67, 0x36, + 0x57, 0x63, 0x7a, 0x44, 0x57, 0x52, 0x50, 0x6d, 0x75, 0x32, 0x67, 0x69, 0x44, 0x6c, 0x6d, 0x0a, + 0x31, 0x4c, 0x5a, 0x31, 0x35, 0x56, 0x67, 0x49, 0x77, 0x78, 0x64, 0x55, 0x6d, 0x39, 0x48, 0x35, + 0x32, 0x6e, 0x44, 0x4a, 0x35, 0x54, 0x64, 0x38, 0x4e, 0x4b, 0x6e, 0x53, 0x43, 0x67, 0x58, 0x4b, + 0x62, 0x52, 0x33, 0x47, 0x61, 0x4e, 0x79, 0x66, 0x75, 0x74, 0x73, 0x73, 0x58, 0x72, 0x74, 0x6d, + 0x58, 0x33, 0x42, 0x53, 0x55, 0x78, 0x54, 0x62, 0x6c, 0x5a, 0x48, 0x4e, 0x31, 0x6b, 0x4b, 0x33, + 0x0a, 0x44, 0x52, 0x71, 0x79, 0x74, 0x79, 0x44, 0x52, 0x61, 0x72, 0x4b, 0x49, 0x37, 0x52, 0x58, + 0x52, 0x48, 0x35, 0x46, 0x79, 0x55, 0x32, 0x76, 0x4d, 0x79, 0x49, 0x4c, 0x5a, 0x2b, 0x7a, 0x6b, + 0x45, 0x51, 0x69, 0x75, 0x68, 0x36, 0x62, 0x54, 0x79, 0x43, 0x2b, 0x57, 0x52, 0x37, 0x42, 0x30, + 0x72, 0x44, 0x6a, 0x6f, 0x38, 0x4c, 0x78, 0x72, 0x30, 0x72, 0x72, 0x31, 0x2b, 0x78, 0x59, 0x67, + 0x43, 0x0a, 0x32, 0x4c, 0x50, 0x68, 0x59, 0x63, 0x36, 0x4e, 0x71, 0x6b, 0x6f, 0x76, 0x73, 0x78, + 0x6a, 0x63, 0x33, 0x34, 0x37, 0x72, 0x2f, 0x7a, 0x4e, 0x32, 0x58, 0x45, 0x6d, 0x4b, 0x74, 0x67, + 0x46, 0x44, 0x59, 0x49, 0x71, 0x65, 0x59, 0x5a, 0x47, 0x31, 0x75, 0x4b, 0x36, 0x65, 0x53, 0x59, + 0x4c, 0x32, 0x4d, 0x48, 0x69, 0x32, 0x39, 0x77, 0x33, 0x49, 0x4a, 0x55, 0x4a, 0x64, 0x57, 0x44, + 0x41, 0x4d, 0x0a, 0x48, 0x46, 0x55, 0x64, 0x58, 0x64, 0x77, 0x43, 0x63, 0x2f, 0x62, 0x67, 0x49, + 0x6b, 0x6c, 0x72, 0x35, 0x31, 0x4d, 0x45, 0x69, 0x39, 0x4d, 0x42, 0x70, 0x4a, 0x39, 0x55, 0x43, + 0x77, 0x55, 0x41, 0x68, 0x2b, 0x78, 0x6b, 0x63, 0x42, 0x48, 0x70, 0x4d, 0x76, 0x6f, 0x34, 0x38, + 0x34, 0x75, 0x6c, 0x6f, 0x61, 0x36, 0x6d, 0x77, 0x74, 0x36, 0x32, 0x69, 0x79, 0x57, 0x36, 0x70, + 0x6e, 0x4c, 0x58, 0x0a, 0x78, 0x74, 0x4e, 0x6f, 0x61, 0x53, 0x6a, 0x4b, 0x2b, 0x52, 0x43, 0x4f, + 0x4b, 0x74, 0x57, 0x64, 0x61, 0x7a, 0x70, 0x73, 0x77, 0x36, 0x39, 0x45, 0x44, 0x6d, 0x39, 0x76, + 0x70, 0x4e, 0x32, 0x47, 0x34, 0x4e, 0x52, 0x47, 0x6f, 0x6a, 0x62, 0x4b, 0x59, 0x6a, 0x66, 0x33, + 0x44, 0x6e, 0x2b, 0x6e, 0x43, 0x6d, 0x54, 0x64, 0x36, 0x71, 0x4c, 0x75, 0x41, 0x63, 0x53, 0x62, + 0x4d, 0x31, 0x62, 0x77, 0x0a, 0x4b, 0x43, 0x65, 0x64, 0x70, 0x56, 0x6f, 0x55, 0x6c, 0x6a, 0x72, + 0x43, 0x68, 0x50, 0x62, 0x50, 0x55, 0x39, 0x30, 0x2b, 0x46, 0x50, 0x2b, 0x59, 0x54, 0x33, 0x6e, + 0x6a, 0x51, 0x2f, 0x2b, 0x52, 0x36, 0x68, 0x59, 0x55, 0x78, 0x31, 0x6e, 0x53, 0x62, 0x6c, 0x7a, + 0x37, 0x4f, 0x6d, 0x75, 0x2b, 0x62, 0x2b, 0x57, 0x35, 0x79, 0x71, 0x72, 0x72, 0x69, 0x6f, 0x30, + 0x38, 0x78, 0x50, 0x64, 0x37, 0x0a, 0x2f, 0x51, 0x70, 0x37, 0x32, 0x30, 0x52, 0x35, 0x43, 0x61, + 0x6a, 0x34, 0x4d, 0x70, 0x57, 0x65, 0x44, 0x42, 0x65, 0x78, 0x32, 0x68, 0x41, 0x51, 0x32, 0x39, + 0x44, 0x30, 0x39, 0x70, 0x53, 0x66, 0x5a, 0x35, 0x63, 0x52, 0x32, 0x63, 0x4c, 0x4a, 0x6b, 0x70, + 0x50, 0x53, 0x66, 0x4f, 0x76, 0x62, 0x76, 0x74, 0x4f, 0x56, 0x61, 0x6c, 0x30, 0x6d, 0x36, 0x6c, + 0x34, 0x30, 0x48, 0x4a, 0x52, 0x6c, 0x0a, 0x2f, 0x56, 0x67, 0x2f, 0x63, 0x42, 0x51, 0x67, 0x46, + 0x47, 0x54, 0x39, 0x66, 0x6d, 0x45, 0x4c, 0x36, 0x38, 0x5a, 0x37, 0x48, 0x61, 0x31, 0x76, 0x34, + 0x44, 0x61, 0x7a, 0x47, 0x44, 0x32, 0x2b, 0x71, 0x52, 0x58, 0x69, 0x45, 0x2b, 0x49, 0x5a, 0x53, + 0x55, 0x47, 0x7a, 0x33, 0x4a, 0x4e, 0x7a, 0x59, 0x6d, 0x42, 0x48, 0x75, 0x53, 0x43, 0x51, 0x6d, + 0x39, 0x66, 0x2f, 0x74, 0x69, 0x4a, 0x35, 0x0a, 0x53, 0x51, 0x46, 0x78, 0x6b, 0x47, 0x38, 0x49, + 0x32, 0x45, 0x33, 0x68, 0x73, 0x6c, 0x38, 0x4b, 0x33, 0x65, 0x4d, 0x4d, 0x61, 0x6b, 0x45, 0x43, + 0x66, 0x34, 0x79, 0x53, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x58, 0x35, + 0x30, 0x39, 0x20, 0x43, 0x52, 0x4c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +#define INTERMEDIATE_CERT_DER_LENGTH 2057 +UA_Byte INTERMEDIATE_CERT_DER_DATA[2057] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, + 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x46, + 0x77, 0x6a, 0x43, 0x43, 0x41, 0x36, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, + 0x54, 0x32, 0x55, 0x75, 0x68, 0x65, 0x71, 0x72, 0x77, 0x30, 0x34, 0x50, 0x76, 0x54, 0x56, 0x79, + 0x32, 0x73, 0x46, 0x44, 0x4e, 0x56, 0x4e, 0x38, 0x5a, 0x30, 0x63, 0x77, 0x44, 0x51, 0x59, 0x4a, + 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x4c, 0x0a, 0x42, 0x51, 0x41, + 0x77, 0x5a, 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, + 0x43, 0x52, 0x45, 0x55, 0x78, 0x44, 0x6a, 0x41, 0x4d, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, + 0x4d, 0x42, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x51, 0x30, 0x77, 0x43, 0x77, 0x59, + 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x52, 0x44, 0x61, 0x58, 0x52, 0x35, 0x0a, 0x4d, 0x52, + 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x41, 0x78, 0x50, 0x63, 0x6d, + 0x64, 0x68, 0x62, 0x6d, 0x6c, 0x36, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x45, 0x44, + 0x41, 0x4f, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x73, 0x4d, 0x42, 0x30, 0x39, 0x79, 0x5a, 0x31, + 0x56, 0x75, 0x61, 0x58, 0x51, 0x78, 0x44, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, + 0x41, 0x4d, 0x4d, 0x42, 0x6c, 0x4a, 0x76, 0x62, 0x33, 0x52, 0x44, 0x51, 0x54, 0x41, 0x65, 0x46, + 0x77, 0x30, 0x79, 0x4e, 0x44, 0x41, 0x35, 0x4d, 0x54, 0x45, 0x78, 0x4d, 0x54, 0x55, 0x33, 0x4d, + 0x7a, 0x5a, 0x61, 0x46, 0x77, 0x30, 0x7a, 0x4e, 0x44, 0x41, 0x35, 0x4d, 0x44, 0x6b, 0x78, 0x4d, + 0x54, 0x55, 0x33, 0x4d, 0x7a, 0x5a, 0x61, 0x4d, 0x47, 0x34, 0x78, 0x43, 0x7a, 0x41, 0x4a, 0x0a, + 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6b, 0x52, 0x46, 0x4d, 0x51, 0x34, 0x77, + 0x44, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x56, 0x54, 0x64, 0x47, 0x46, 0x30, + 0x5a, 0x54, 0x45, 0x4e, 0x4d, 0x41, 0x73, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x77, 0x77, 0x45, + 0x51, 0x32, 0x6c, 0x30, 0x65, 0x54, 0x45, 0x56, 0x4d, 0x42, 0x4d, 0x47, 0x41, 0x31, 0x55, 0x45, + 0x0a, 0x43, 0x67, 0x77, 0x4d, 0x54, 0x33, 0x4a, 0x6e, 0x59, 0x57, 0x35, 0x70, 0x65, 0x6d, 0x46, + 0x30, 0x61, 0x57, 0x39, 0x75, 0x4d, 0x52, 0x41, 0x77, 0x44, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, + 0x4c, 0x44, 0x41, 0x64, 0x50, 0x63, 0x6d, 0x64, 0x56, 0x62, 0x6d, 0x6c, 0x30, 0x4d, 0x52, 0x63, + 0x77, 0x46, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41, 0x35, 0x4a, 0x62, 0x6e, 0x52, + 0x6c, 0x0a, 0x63, 0x6d, 0x31, 0x6c, 0x5a, 0x47, 0x6c, 0x68, 0x64, 0x47, 0x56, 0x44, 0x51, 0x54, + 0x43, 0x43, 0x41, 0x69, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, + 0x63, 0x4e, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x49, 0x50, 0x41, 0x44, + 0x43, 0x43, 0x41, 0x67, 0x6f, 0x43, 0x67, 0x67, 0x49, 0x42, 0x41, 0x4e, 0x31, 0x4e, 0x4f, 0x55, + 0x72, 0x63, 0x0a, 0x66, 0x68, 0x4e, 0x51, 0x4a, 0x46, 0x74, 0x42, 0x4a, 0x55, 0x39, 0x51, 0x47, + 0x35, 0x34, 0x4f, 0x2f, 0x46, 0x63, 0x67, 0x61, 0x4a, 0x4a, 0x2b, 0x53, 0x69, 0x79, 0x73, 0x4c, + 0x36, 0x4d, 0x49, 0x37, 0x50, 0x42, 0x4e, 0x55, 0x45, 0x31, 0x56, 0x6a, 0x6d, 0x59, 0x59, 0x38, + 0x35, 0x2f, 0x34, 0x57, 0x43, 0x57, 0x58, 0x66, 0x69, 0x47, 0x39, 0x75, 0x58, 0x79, 0x42, 0x6c, + 0x6b, 0x31, 0x55, 0x0a, 0x62, 0x70, 0x5a, 0x61, 0x4b, 0x72, 0x76, 0x51, 0x59, 0x4b, 0x64, 0x59, + 0x52, 0x50, 0x5a, 0x39, 0x48, 0x71, 0x66, 0x76, 0x42, 0x43, 0x6b, 0x6d, 0x68, 0x4a, 0x53, 0x36, + 0x6e, 0x4a, 0x57, 0x75, 0x38, 0x53, 0x39, 0x41, 0x43, 0x4a, 0x34, 0x47, 0x47, 0x51, 0x6d, 0x63, + 0x54, 0x69, 0x68, 0x71, 0x35, 0x6f, 0x72, 0x5a, 0x6f, 0x57, 0x73, 0x75, 0x32, 0x2b, 0x46, 0x7a, + 0x4d, 0x71, 0x45, 0x6b, 0x0a, 0x4d, 0x69, 0x2f, 0x47, 0x52, 0x6a, 0x2b, 0x4d, 0x53, 0x70, 0x6f, + 0x57, 0x39, 0x68, 0x55, 0x74, 0x44, 0x6a, 0x42, 0x33, 0x6a, 0x74, 0x63, 0x4b, 0x31, 0x73, 0x68, + 0x38, 0x53, 0x46, 0x74, 0x66, 0x48, 0x49, 0x44, 0x42, 0x66, 0x31, 0x4b, 0x53, 0x4c, 0x5a, 0x46, + 0x6b, 0x4c, 0x6a, 0x55, 0x43, 0x4a, 0x75, 0x65, 0x6b, 0x6d, 0x67, 0x31, 0x47, 0x78, 0x63, 0x34, + 0x70, 0x37, 0x6f, 0x78, 0x65, 0x0a, 0x6f, 0x45, 0x43, 0x49, 0x6b, 0x57, 0x4e, 0x54, 0x30, 0x52, + 0x4e, 0x53, 0x64, 0x4a, 0x6f, 0x2b, 0x73, 0x4f, 0x63, 0x6d, 0x6a, 0x59, 0x38, 0x6a, 0x32, 0x77, + 0x43, 0x4e, 0x69, 0x7a, 0x6c, 0x32, 0x76, 0x36, 0x42, 0x43, 0x72, 0x41, 0x57, 0x6f, 0x75, 0x4d, + 0x68, 0x6f, 0x78, 0x6a, 0x6c, 0x54, 0x41, 0x33, 0x33, 0x66, 0x43, 0x73, 0x2b, 0x2b, 0x6c, 0x58, + 0x6b, 0x4d, 0x2b, 0x79, 0x38, 0x6e, 0x0a, 0x46, 0x7a, 0x41, 0x6f, 0x75, 0x67, 0x68, 0x4b, 0x62, + 0x56, 0x31, 0x43, 0x69, 0x71, 0x59, 0x6a, 0x65, 0x68, 0x36, 0x6d, 0x56, 0x6a, 0x38, 0x68, 0x69, + 0x30, 0x39, 0x32, 0x55, 0x66, 0x33, 0x6a, 0x62, 0x43, 0x78, 0x6c, 0x4a, 0x73, 0x6f, 0x73, 0x46, + 0x2b, 0x4a, 0x65, 0x78, 0x54, 0x59, 0x56, 0x64, 0x41, 0x4e, 0x36, 0x74, 0x72, 0x50, 0x75, 0x4c, + 0x2f, 0x4a, 0x51, 0x4b, 0x66, 0x4b, 0x54, 0x0a, 0x4a, 0x39, 0x74, 0x31, 0x44, 0x62, 0x71, 0x6e, + 0x44, 0x74, 0x38, 0x50, 0x75, 0x43, 0x55, 0x45, 0x67, 0x63, 0x44, 0x76, 0x71, 0x48, 0x51, 0x4a, + 0x58, 0x58, 0x34, 0x53, 0x33, 0x59, 0x66, 0x65, 0x57, 0x62, 0x6e, 0x74, 0x51, 0x63, 0x36, 0x62, + 0x5a, 0x34, 0x4a, 0x5a, 0x44, 0x5a, 0x63, 0x46, 0x35, 0x6f, 0x67, 0x39, 0x47, 0x69, 0x6f, 0x61, + 0x5a, 0x2b, 0x75, 0x55, 0x45, 0x63, 0x4e, 0x62, 0x0a, 0x47, 0x4d, 0x32, 0x76, 0x33, 0x31, 0x5a, + 0x44, 0x74, 0x31, 0x45, 0x46, 0x41, 0x7a, 0x74, 0x6d, 0x74, 0x46, 0x74, 0x72, 0x70, 0x68, 0x52, + 0x50, 0x79, 0x5a, 0x4e, 0x61, 0x76, 0x39, 0x73, 0x63, 0x52, 0x77, 0x75, 0x50, 0x37, 0x51, 0x72, + 0x49, 0x62, 0x63, 0x66, 0x45, 0x63, 0x63, 0x51, 0x55, 0x70, 0x33, 0x61, 0x2f, 0x62, 0x62, 0x31, + 0x49, 0x51, 0x50, 0x4b, 0x2b, 0x4b, 0x59, 0x50, 0x67, 0x0a, 0x31, 0x50, 0x61, 0x67, 0x58, 0x57, + 0x59, 0x44, 0x62, 0x69, 0x6c, 0x55, 0x42, 0x4a, 0x57, 0x6d, 0x69, 0x32, 0x52, 0x31, 0x69, 0x52, + 0x4b, 0x78, 0x39, 0x59, 0x4e, 0x61, 0x68, 0x34, 0x45, 0x51, 0x49, 0x6f, 0x49, 0x72, 0x61, 0x61, + 0x66, 0x54, 0x6a, 0x78, 0x73, 0x6f, 0x6e, 0x50, 0x2f, 0x30, 0x55, 0x79, 0x62, 0x6b, 0x71, 0x65, + 0x6e, 0x73, 0x4b, 0x4d, 0x47, 0x71, 0x58, 0x54, 0x2f, 0x55, 0x0a, 0x64, 0x34, 0x52, 0x33, 0x36, + 0x50, 0x31, 0x64, 0x44, 0x43, 0x6b, 0x6b, 0x4e, 0x2b, 0x4b, 0x59, 0x64, 0x55, 0x42, 0x4d, 0x44, + 0x72, 0x76, 0x66, 0x69, 0x51, 0x34, 0x47, 0x64, 0x4e, 0x6a, 0x4c, 0x5a, 0x61, 0x2b, 0x49, 0x32, + 0x75, 0x50, 0x50, 0x6c, 0x55, 0x6e, 0x76, 0x72, 0x38, 0x7a, 0x67, 0x43, 0x73, 0x45, 0x77, 0x4f, + 0x7a, 0x75, 0x46, 0x32, 0x5a, 0x73, 0x32, 0x4f, 0x6f, 0x32, 0x50, 0x0a, 0x50, 0x52, 0x63, 0x7a, + 0x50, 0x50, 0x5a, 0x44, 0x2b, 0x61, 0x36, 0x46, 0x64, 0x74, 0x39, 0x44, 0x65, 0x74, 0x73, 0x47, + 0x77, 0x36, 0x35, 0x32, 0x49, 0x47, 0x38, 0x65, 0x49, 0x59, 0x70, 0x33, 0x63, 0x47, 0x2f, 0x4b, + 0x43, 0x74, 0x66, 0x6b, 0x6f, 0x30, 0x76, 0x58, 0x6f, 0x46, 0x4a, 0x73, 0x43, 0x4e, 0x4b, 0x36, + 0x2f, 0x45, 0x6e, 0x65, 0x31, 0x4e, 0x66, 0x72, 0x45, 0x6e, 0x7a, 0x79, 0x0a, 0x32, 0x30, 0x67, + 0x7a, 0x7a, 0x39, 0x4a, 0x55, 0x6d, 0x35, 0x7a, 0x68, 0x73, 0x38, 0x54, 0x68, 0x59, 0x63, 0x34, + 0x75, 0x35, 0x6f, 0x41, 0x2f, 0x78, 0x48, 0x6f, 0x79, 0x76, 0x79, 0x57, 0x46, 0x38, 0x74, 0x39, + 0x31, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x47, 0x6a, 0x59, 0x44, 0x42, 0x65, 0x4d, 0x41, 0x38, + 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2f, 0x77, 0x51, 0x46, 0x0a, 0x4d, 0x41, + 0x4d, 0x42, 0x41, 0x66, 0x38, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x50, 0x42, 0x41, + 0x51, 0x44, 0x41, 0x67, 0x45, 0x47, 0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, + 0x51, 0x57, 0x42, 0x42, 0x52, 0x6c, 0x76, 0x43, 0x32, 0x55, 0x61, 0x31, 0x32, 0x64, 0x34, 0x59, + 0x51, 0x31, 0x4f, 0x51, 0x79, 0x2b, 0x32, 0x43, 0x76, 0x4c, 0x6e, 0x4c, 0x47, 0x72, 0x0a, 0x41, + 0x44, 0x41, 0x66, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x53, 0x4d, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, + 0x42, 0x54, 0x53, 0x57, 0x39, 0x59, 0x70, 0x5a, 0x4c, 0x43, 0x73, 0x74, 0x43, 0x30, 0x50, 0x54, + 0x39, 0x32, 0x39, 0x5a, 0x56, 0x6d, 0x43, 0x78, 0x30, 0x48, 0x30, 0x4a, 0x6a, 0x41, 0x4e, 0x42, + 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x0a, + 0x41, 0x41, 0x4f, 0x43, 0x41, 0x67, 0x45, 0x41, 0x67, 0x65, 0x48, 0x74, 0x75, 0x57, 0x4b, 0x38, + 0x35, 0x31, 0x68, 0x4f, 0x48, 0x58, 0x55, 0x52, 0x62, 0x59, 0x71, 0x43, 0x75, 0x37, 0x4f, 0x58, + 0x6c, 0x35, 0x61, 0x73, 0x69, 0x2b, 0x61, 0x39, 0x44, 0x59, 0x72, 0x4b, 0x66, 0x34, 0x4c, 0x50, + 0x71, 0x35, 0x50, 0x78, 0x72, 0x48, 0x38, 0x2b, 0x64, 0x56, 0x33, 0x6c, 0x49, 0x44, 0x6a, 0x38, + 0x0a, 0x59, 0x47, 0x5a, 0x6c, 0x34, 0x34, 0x64, 0x37, 0x34, 0x6f, 0x6c, 0x38, 0x4a, 0x72, 0x71, + 0x2f, 0x4b, 0x59, 0x64, 0x39, 0x34, 0x71, 0x53, 0x46, 0x76, 0x71, 0x30, 0x39, 0x39, 0x43, 0x66, + 0x42, 0x6c, 0x53, 0x65, 0x61, 0x6d, 0x44, 0x4d, 0x71, 0x4a, 0x30, 0x54, 0x4d, 0x76, 0x68, 0x4d, + 0x62, 0x37, 0x38, 0x68, 0x75, 0x7a, 0x48, 0x4f, 0x63, 0x59, 0x73, 0x72, 0x73, 0x6e, 0x4c, 0x4f, + 0x77, 0x0a, 0x45, 0x32, 0x6f, 0x46, 0x43, 0x65, 0x41, 0x45, 0x2b, 0x78, 0x77, 0x2f, 0x68, 0x2f, + 0x53, 0x4c, 0x75, 0x62, 0x76, 0x6e, 0x59, 0x6d, 0x43, 0x43, 0x5a, 0x67, 0x4f, 0x50, 0x54, 0x4f, + 0x32, 0x74, 0x51, 0x5a, 0x72, 0x34, 0x4d, 0x39, 0x75, 0x44, 0x6e, 0x52, 0x37, 0x7a, 0x49, 0x66, + 0x38, 0x6c, 0x59, 0x47, 0x56, 0x33, 0x50, 0x6d, 0x43, 0x6e, 0x78, 0x63, 0x78, 0x2b, 0x4a, 0x68, + 0x76, 0x65, 0x0a, 0x6d, 0x74, 0x47, 0x62, 0x6b, 0x2f, 0x6d, 0x35, 0x6a, 0x73, 0x68, 0x52, 0x6c, + 0x2b, 0x44, 0x30, 0x62, 0x53, 0x64, 0x76, 0x52, 0x36, 0x52, 0x56, 0x37, 0x71, 0x4b, 0x72, 0x70, + 0x4c, 0x50, 0x5a, 0x38, 0x74, 0x42, 0x79, 0x46, 0x2b, 0x53, 0x2b, 0x63, 0x45, 0x4d, 0x6f, 0x6b, + 0x6f, 0x47, 0x35, 0x6d, 0x63, 0x59, 0x38, 0x68, 0x75, 0x39, 0x38, 0x7a, 0x36, 0x79, 0x65, 0x73, + 0x43, 0x73, 0x70, 0x0a, 0x79, 0x43, 0x64, 0x46, 0x74, 0x55, 0x45, 0x34, 0x69, 0x77, 0x64, 0x70, + 0x4b, 0x2f, 0x55, 0x56, 0x48, 0x61, 0x31, 0x39, 0x44, 0x52, 0x72, 0x6f, 0x48, 0x64, 0x41, 0x48, + 0x61, 0x36, 0x37, 0x79, 0x38, 0x79, 0x73, 0x50, 0x46, 0x69, 0x34, 0x65, 0x76, 0x63, 0x50, 0x32, + 0x44, 0x65, 0x48, 0x50, 0x70, 0x32, 0x6f, 0x78, 0x4a, 0x73, 0x2b, 0x38, 0x4b, 0x73, 0x73, 0x4c, + 0x44, 0x31, 0x30, 0x6f, 0x0a, 0x78, 0x6a, 0x4a, 0x37, 0x6b, 0x43, 0x64, 0x6e, 0x70, 0x78, 0x4a, + 0x5a, 0x64, 0x49, 0x74, 0x41, 0x39, 0x76, 0x54, 0x44, 0x75, 0x69, 0x48, 0x57, 0x79, 0x66, 0x69, + 0x79, 0x4a, 0x75, 0x35, 0x6f, 0x30, 0x71, 0x4e, 0x4d, 0x49, 0x50, 0x50, 0x57, 0x4d, 0x76, 0x51, + 0x46, 0x45, 0x74, 0x6f, 0x61, 0x76, 0x34, 0x42, 0x67, 0x2b, 0x32, 0x74, 0x66, 0x4b, 0x70, 0x61, + 0x52, 0x41, 0x33, 0x57, 0x64, 0x0a, 0x42, 0x65, 0x53, 0x2f, 0x37, 0x4d, 0x45, 0x6e, 0x36, 0x65, + 0x72, 0x37, 0x73, 0x43, 0x64, 0x2b, 0x42, 0x35, 0x2b, 0x4d, 0x79, 0x4b, 0x78, 0x46, 0x4f, 0x66, + 0x75, 0x52, 0x74, 0x5a, 0x70, 0x6c, 0x71, 0x35, 0x41, 0x42, 0x4c, 0x69, 0x37, 0x53, 0x35, 0x64, + 0x76, 0x6d, 0x6e, 0x79, 0x48, 0x37, 0x51, 0x2f, 0x76, 0x4b, 0x53, 0x51, 0x53, 0x75, 0x39, 0x34, + 0x66, 0x66, 0x52, 0x78, 0x61, 0x4c, 0x0a, 0x56, 0x69, 0x63, 0x6e, 0x6f, 0x6f, 0x4a, 0x4d, 0x38, + 0x44, 0x6e, 0x47, 0x6c, 0x70, 0x43, 0x75, 0x35, 0x35, 0x61, 0x50, 0x46, 0x56, 0x6e, 0x54, 0x46, + 0x6a, 0x37, 0x30, 0x43, 0x47, 0x61, 0x50, 0x72, 0x61, 0x4b, 0x72, 0x69, 0x6a, 0x62, 0x68, 0x35, + 0x4e, 0x4a, 0x51, 0x43, 0x7a, 0x6c, 0x62, 0x31, 0x2f, 0x65, 0x52, 0x48, 0x31, 0x6c, 0x4d, 0x55, + 0x6b, 0x31, 0x57, 0x37, 0x6d, 0x41, 0x68, 0x0a, 0x75, 0x39, 0x33, 0x44, 0x2b, 0x79, 0x2f, 0x65, + 0x72, 0x46, 0x4f, 0x75, 0x2f, 0x6a, 0x58, 0x73, 0x44, 0x6e, 0x69, 0x34, 0x4a, 0x4c, 0x68, 0x72, + 0x4d, 0x65, 0x34, 0x45, 0x7a, 0x6d, 0x78, 0x75, 0x2b, 0x6c, 0x7a, 0x6b, 0x6b, 0x58, 0x43, 0x68, + 0x36, 0x39, 0x36, 0x58, 0x6a, 0x59, 0x49, 0x45, 0x62, 0x41, 0x42, 0x6f, 0x66, 0x62, 0x45, 0x4c, + 0x30, 0x74, 0x46, 0x56, 0x50, 0x6e, 0x68, 0x37, 0x0a, 0x51, 0x55, 0x42, 0x37, 0x65, 0x59, 0x4a, + 0x63, 0x67, 0x6b, 0x61, 0x42, 0x6e, 0x39, 0x64, 0x6b, 0x31, 0x38, 0x61, 0x73, 0x6f, 0x78, 0x73, + 0x54, 0x41, 0x51, 0x73, 0x30, 0x6b, 0x41, 0x61, 0x52, 0x71, 0x79, 0x70, 0x73, 0x63, 0x4a, 0x46, + 0x44, 0x56, 0x6d, 0x67, 0x74, 0x45, 0x78, 0x53, 0x4e, 0x54, 0x72, 0x4a, 0x78, 0x50, 0x62, 0x7a, + 0x52, 0x33, 0x6d, 0x72, 0x2f, 0x69, 0x6f, 0x64, 0x6d, 0x0a, 0x5a, 0x7a, 0x57, 0x37, 0x54, 0x39, + 0x59, 0x33, 0x4f, 0x4e, 0x45, 0x31, 0x67, 0x79, 0x74, 0x38, 0x75, 0x51, 0x53, 0x44, 0x58, 0x62, + 0x4d, 0x6c, 0x6b, 0x71, 0x6d, 0x55, 0x76, 0x49, 0x61, 0x6f, 0x42, 0x4d, 0x79, 0x43, 0x4c, 0x56, + 0x31, 0x31, 0x6a, 0x44, 0x66, 0x6a, 0x6b, 0x51, 0x47, 0x78, 0x41, 0x53, 0x77, 0x3d, 0x0a, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, + 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +/* Contains the application certificate */ +#define INTERMEDIATE_CRL_PEM_LENGTH 1121 +UA_Byte INTERMEDIATE_CRL_PEM_DATA[1121] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x58, 0x35, 0x30, 0x39, 0x20, + 0x43, 0x52, 0x4c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x45, 0x6a, 0x43, + 0x42, 0x2b, 0x77, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, + 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x75, 0x4d, 0x51, 0x73, + 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x45, 0x52, 0x54, 0x45, + 0x4f, 0x4d, 0x41, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0a, 0x43, 0x41, 0x77, 0x46, 0x55, 0x33, + 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x44, 0x54, 0x41, 0x4c, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, + 0x63, 0x4d, 0x42, 0x45, 0x4e, 0x70, 0x64, 0x48, 0x6b, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, + 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x44, 0x45, 0x39, 0x79, 0x5a, 0x32, 0x46, 0x75, 0x61, 0x58, + 0x70, 0x68, 0x64, 0x47, 0x6c, 0x76, 0x62, 0x6a, 0x45, 0x51, 0x0a, 0x4d, 0x41, 0x34, 0x47, 0x41, + 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x48, 0x54, 0x33, 0x4a, 0x6e, 0x56, 0x57, 0x35, 0x70, 0x64, + 0x44, 0x45, 0x58, 0x4d, 0x42, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4f, 0x53, + 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, 0x74, 0x5a, 0x57, 0x52, 0x70, 0x59, 0x58, 0x52, 0x6c, 0x51, + 0x30, 0x45, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x44, 0x6b, 0x78, 0x0a, 0x4d, 0x54, 0x45, 0x30, + 0x4d, 0x44, 0x49, 0x7a, 0x4d, 0x6c, 0x6f, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x54, 0x41, 0x78, + 0x4d, 0x54, 0x45, 0x30, 0x4d, 0x44, 0x49, 0x7a, 0x4d, 0x6c, 0x6f, 0x77, 0x4a, 0x7a, 0x41, 0x6c, + 0x41, 0x68, 0x51, 0x49, 0x69, 0x49, 0x59, 0x35, 0x35, 0x39, 0x4e, 0x34, 0x73, 0x6f, 0x6d, 0x6b, + 0x2b, 0x49, 0x76, 0x32, 0x63, 0x51, 0x44, 0x44, 0x64, 0x6e, 0x67, 0x4d, 0x0a, 0x6f, 0x52, 0x63, + 0x4e, 0x4d, 0x6a, 0x51, 0x77, 0x4f, 0x54, 0x45, 0x78, 0x4d, 0x54, 0x51, 0x77, 0x4d, 0x6a, 0x49, + 0x32, 0x57, 0x71, 0x41, 0x77, 0x4d, 0x43, 0x34, 0x77, 0x48, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, + 0x6a, 0x42, 0x42, 0x67, 0x77, 0x46, 0x6f, 0x41, 0x55, 0x5a, 0x62, 0x77, 0x74, 0x6c, 0x47, 0x74, + 0x64, 0x6e, 0x65, 0x47, 0x45, 0x4e, 0x54, 0x6b, 0x4d, 0x76, 0x74, 0x67, 0x72, 0x0a, 0x79, 0x35, + 0x79, 0x78, 0x71, 0x77, 0x41, 0x77, 0x43, 0x77, 0x59, 0x44, 0x56, 0x52, 0x30, 0x55, 0x42, 0x41, + 0x51, 0x43, 0x41, 0x68, 0x41, 0x46, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49, + 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x43, 0x41, 0x51, + 0x41, 0x73, 0x6b, 0x45, 0x4f, 0x65, 0x36, 0x4d, 0x56, 0x36, 0x62, 0x54, 0x79, 0x6c, 0x0a, 0x41, + 0x56, 0x50, 0x48, 0x71, 0x47, 0x55, 0x69, 0x42, 0x64, 0x41, 0x53, 0x76, 0x75, 0x68, 0x33, 0x6e, + 0x6a, 0x68, 0x48, 0x4f, 0x6d, 0x5a, 0x42, 0x43, 0x32, 0x31, 0x77, 0x34, 0x51, 0x71, 0x73, 0x7a, + 0x43, 0x32, 0x48, 0x65, 0x38, 0x33, 0x4d, 0x58, 0x66, 0x63, 0x41, 0x7a, 0x4b, 0x6b, 0x51, 0x55, + 0x61, 0x6d, 0x4c, 0x5a, 0x45, 0x76, 0x43, 0x4d, 0x32, 0x2f, 0x77, 0x4e, 0x74, 0x58, 0x6c, 0x0a, + 0x59, 0x55, 0x67, 0x79, 0x66, 0x53, 0x70, 0x52, 0x4e, 0x6b, 0x70, 0x56, 0x6e, 0x6a, 0x4a, 0x66, + 0x35, 0x4f, 0x6d, 0x6a, 0x50, 0x75, 0x53, 0x75, 0x46, 0x76, 0x39, 0x69, 0x64, 0x78, 0x46, 0x68, + 0x34, 0x66, 0x44, 0x35, 0x37, 0x71, 0x41, 0x38, 0x2f, 0x51, 0x70, 0x4f, 0x31, 0x61, 0x61, 0x44, + 0x65, 0x71, 0x4d, 0x41, 0x74, 0x47, 0x37, 0x72, 0x53, 0x77, 0x4a, 0x69, 0x2b, 0x67, 0x7a, 0x69, + 0x0a, 0x36, 0x35, 0x38, 0x36, 0x6d, 0x73, 0x33, 0x58, 0x72, 0x72, 0x7a, 0x51, 0x2b, 0x33, 0x69, + 0x54, 0x69, 0x50, 0x52, 0x49, 0x44, 0x45, 0x4b, 0x71, 0x2b, 0x72, 0x69, 0x69, 0x2b, 0x52, 0x4b, + 0x68, 0x41, 0x4b, 0x64, 0x79, 0x57, 0x63, 0x2f, 0x79, 0x6f, 0x4a, 0x6c, 0x4b, 0x75, 0x30, 0x2f, + 0x6f, 0x42, 0x6b, 0x73, 0x63, 0x77, 0x67, 0x65, 0x58, 0x42, 0x61, 0x52, 0x33, 0x4c, 0x4f, 0x6b, + 0x5a, 0x0a, 0x53, 0x6b, 0x2b, 0x73, 0x76, 0x70, 0x4a, 0x6f, 0x32, 0x36, 0x75, 0x59, 0x4d, 0x45, + 0x52, 0x36, 0x43, 0x31, 0x70, 0x37, 0x42, 0x48, 0x79, 0x43, 0x78, 0x62, 0x59, 0x4c, 0x4a, 0x30, + 0x58, 0x61, 0x4d, 0x46, 0x51, 0x54, 0x54, 0x57, 0x76, 0x37, 0x37, 0x34, 0x6f, 0x33, 0x63, 0x4a, + 0x42, 0x53, 0x45, 0x58, 0x79, 0x74, 0x2b, 0x58, 0x78, 0x52, 0x69, 0x75, 0x6e, 0x6c, 0x43, 0x49, + 0x42, 0x31, 0x0a, 0x75, 0x46, 0x77, 0x36, 0x43, 0x44, 0x44, 0x2f, 0x57, 0x63, 0x76, 0x72, 0x43, + 0x76, 0x59, 0x55, 0x77, 0x71, 0x63, 0x43, 0x77, 0x31, 0x2b, 0x53, 0x47, 0x66, 0x46, 0x2b, 0x68, + 0x51, 0x74, 0x6f, 0x77, 0x4d, 0x33, 0x6a, 0x4c, 0x73, 0x33, 0x71, 0x50, 0x57, 0x59, 0x61, 0x2b, + 0x66, 0x67, 0x69, 0x58, 0x33, 0x71, 0x70, 0x38, 0x72, 0x53, 0x77, 0x65, 0x39, 0x32, 0x69, 0x5a, + 0x76, 0x44, 0x4e, 0x0a, 0x7a, 0x4e, 0x72, 0x6f, 0x34, 0x64, 0x5a, 0x4a, 0x46, 0x42, 0x59, 0x65, + 0x61, 0x55, 0x70, 0x30, 0x46, 0x48, 0x6c, 0x6e, 0x71, 0x56, 0x2b, 0x46, 0x6c, 0x72, 0x77, 0x32, + 0x5a, 0x6c, 0x38, 0x41, 0x48, 0x53, 0x4e, 0x33, 0x69, 0x75, 0x70, 0x53, 0x33, 0x74, 0x74, 0x2b, + 0x39, 0x56, 0x31, 0x76, 0x63, 0x75, 0x45, 0x34, 0x2b, 0x70, 0x78, 0x64, 0x68, 0x73, 0x32, 0x44, + 0x4c, 0x78, 0x38, 0x46, 0x0a, 0x78, 0x6d, 0x6d, 0x39, 0x41, 0x67, 0x66, 0x50, 0x32, 0x49, 0x71, + 0x33, 0x62, 0x47, 0x4c, 0x4a, 0x69, 0x42, 0x32, 0x76, 0x39, 0x74, 0x4d, 0x76, 0x70, 0x63, 0x32, + 0x63, 0x4e, 0x61, 0x45, 0x58, 0x33, 0x4b, 0x34, 0x4a, 0x48, 0x4f, 0x48, 0x78, 0x38, 0x6a, 0x6b, + 0x65, 0x34, 0x6b, 0x6f, 0x66, 0x66, 0x4f, 0x44, 0x70, 0x77, 0x36, 0x70, 0x48, 0x71, 0x71, 0x61, + 0x64, 0x73, 0x47, 0x54, 0x63, 0x0a, 0x6d, 0x55, 0x56, 0x75, 0x4f, 0x45, 0x66, 0x35, 0x47, 0x72, + 0x70, 0x77, 0x37, 0x67, 0x54, 0x68, 0x70, 0x41, 0x52, 0x2b, 0x38, 0x37, 0x32, 0x45, 0x66, 0x41, + 0x43, 0x58, 0x72, 0x4a, 0x6f, 0x33, 0x63, 0x73, 0x45, 0x2b, 0x48, 0x74, 0x49, 0x2b, 0x50, 0x69, + 0x4b, 0x48, 0x58, 0x37, 0x6f, 0x38, 0x47, 0x75, 0x61, 0x49, 0x63, 0x56, 0x6d, 0x77, 0x42, 0x74, + 0x59, 0x33, 0x35, 0x52, 0x75, 0x44, 0x0a, 0x4e, 0x56, 0x6f, 0x34, 0x58, 0x36, 0x36, 0x49, 0x52, + 0x47, 0x6d, 0x65, 0x38, 0x4a, 0x56, 0x58, 0x64, 0x50, 0x4c, 0x35, 0x6b, 0x76, 0x6b, 0x78, 0x6e, + 0x63, 0x4f, 0x72, 0x73, 0x77, 0x30, 0x42, 0x75, 0x61, 0x48, 0x61, 0x63, 0x76, 0x41, 0x58, 0x6f, + 0x2b, 0x79, 0x42, 0x49, 0x66, 0x4e, 0x78, 0x6b, 0x54, 0x37, 0x67, 0x35, 0x78, 0x69, 0x46, 0x74, + 0x58, 0x49, 0x41, 0x70, 0x36, 0x74, 0x72, 0x0a, 0x36, 0x63, 0x36, 0x52, 0x30, 0x6e, 0x78, 0x70, + 0x63, 0x7a, 0x77, 0x6c, 0x68, 0x43, 0x55, 0x39, 0x34, 0x37, 0x4c, 0x48, 0x34, 0x62, 0x51, 0x74, + 0x66, 0x33, 0x6e, 0x51, 0x6f, 0x30, 0x4e, 0x6e, 0x6e, 0x39, 0x73, 0x74, 0x44, 0x39, 0x38, 0x67, + 0x31, 0x33, 0x6e, 0x63, 0x54, 0x59, 0x59, 0x73, 0x73, 0x32, 0x73, 0x78, 0x35, 0x64, 0x61, 0x5a, + 0x75, 0x56, 0x53, 0x45, 0x79, 0x57, 0x64, 0x72, 0x0a, 0x4e, 0x6a, 0x66, 0x7a, 0x56, 0x33, 0x5a, + 0x49, 0x4d, 0x77, 0x4a, 0x4f, 0x2f, 0x2b, 0x39, 0x6f, 0x67, 0x4e, 0x51, 0x45, 0x37, 0x42, 0x69, + 0x75, 0x35, 0x78, 0x2f, 0x55, 0x62, 0x41, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, + 0x4e, 0x44, 0x20, 0x58, 0x35, 0x30, 0x39, 0x20, 0x43, 0x52, 0x4c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x0a +}; + +#define INTERMEDIATE_EMPTY_CRL_PEM_LENGTH 1064 +UA_Byte INTERMEDIATE_EMPTY_CRL_PEM_DATA[1064] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x58, 0x35, 0x30, 0x39, 0x20, + 0x43, 0x52, 0x4c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, 0x36, 0x54, 0x43, + 0x42, 0x30, 0x67, 0x49, 0x42, 0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, + 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x75, 0x4d, 0x51, 0x73, + 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x47, 0x45, 0x77, 0x4a, 0x45, 0x52, 0x54, 0x45, + 0x4f, 0x4d, 0x41, 0x77, 0x47, 0x41, 0x31, 0x55, 0x45, 0x0a, 0x43, 0x41, 0x77, 0x46, 0x55, 0x33, + 0x52, 0x68, 0x64, 0x47, 0x55, 0x78, 0x44, 0x54, 0x41, 0x4c, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, + 0x63, 0x4d, 0x42, 0x45, 0x4e, 0x70, 0x64, 0x48, 0x6b, 0x78, 0x46, 0x54, 0x41, 0x54, 0x42, 0x67, + 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x44, 0x45, 0x39, 0x79, 0x5a, 0x32, 0x46, 0x75, 0x61, 0x58, + 0x70, 0x68, 0x64, 0x47, 0x6c, 0x76, 0x62, 0x6a, 0x45, 0x51, 0x0a, 0x4d, 0x41, 0x34, 0x47, 0x41, + 0x31, 0x55, 0x45, 0x43, 0x77, 0x77, 0x48, 0x54, 0x33, 0x4a, 0x6e, 0x56, 0x57, 0x35, 0x70, 0x64, + 0x44, 0x45, 0x58, 0x4d, 0x42, 0x55, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41, 0x77, 0x77, 0x4f, 0x53, + 0x57, 0x35, 0x30, 0x5a, 0x58, 0x4a, 0x74, 0x5a, 0x57, 0x52, 0x70, 0x59, 0x58, 0x52, 0x6c, 0x51, + 0x30, 0x45, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x44, 0x6b, 0x78, 0x0a, 0x4d, 0x54, 0x45, 0x79, + 0x4d, 0x44, 0x51, 0x77, 0x4e, 0x6c, 0x6f, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, 0x54, 0x41, 0x78, + 0x4d, 0x54, 0x45, 0x79, 0x4d, 0x44, 0x51, 0x77, 0x4e, 0x6c, 0x71, 0x67, 0x4d, 0x44, 0x41, 0x75, + 0x4d, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51, 0x59, 0x4d, 0x42, 0x61, 0x41, + 0x46, 0x47, 0x57, 0x38, 0x4c, 0x5a, 0x52, 0x72, 0x58, 0x5a, 0x33, 0x68, 0x0a, 0x68, 0x44, 0x55, + 0x35, 0x44, 0x4c, 0x37, 0x59, 0x4b, 0x38, 0x75, 0x63, 0x73, 0x61, 0x73, 0x41, 0x4d, 0x41, 0x73, + 0x47, 0x41, 0x31, 0x55, 0x64, 0x46, 0x41, 0x51, 0x45, 0x41, 0x67, 0x49, 0x51, 0x41, 0x6a, 0x41, + 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, + 0x46, 0x41, 0x41, 0x4f, 0x43, 0x41, 0x67, 0x45, 0x41, 0x64, 0x2b, 0x45, 0x39, 0x0a, 0x65, 0x56, + 0x4b, 0x44, 0x58, 0x4a, 0x6b, 0x62, 0x4c, 0x6b, 0x61, 0x65, 0x35, 0x41, 0x42, 0x70, 0x36, 0x4d, + 0x79, 0x4e, 0x44, 0x43, 0x6d, 0x54, 0x75, 0x39, 0x44, 0x6b, 0x2f, 0x56, 0x75, 0x4b, 0x72, 0x56, + 0x79, 0x78, 0x4e, 0x39, 0x69, 0x4c, 0x36, 0x52, 0x34, 0x69, 0x62, 0x41, 0x79, 0x52, 0x6a, 0x43, + 0x2b, 0x7a, 0x57, 0x6e, 0x42, 0x39, 0x6b, 0x66, 0x54, 0x73, 0x4b, 0x36, 0x77, 0x77, 0x0a, 0x6c, + 0x6a, 0x4b, 0x74, 0x31, 0x30, 0x75, 0x67, 0x47, 0x62, 0x67, 0x76, 0x33, 0x37, 0x72, 0x57, 0x57, + 0x78, 0x49, 0x45, 0x71, 0x57, 0x72, 0x68, 0x69, 0x35, 0x50, 0x58, 0x4d, 0x76, 0x63, 0x6b, 0x49, + 0x62, 0x59, 0x47, 0x35, 0x63, 0x77, 0x5a, 0x59, 0x7a, 0x61, 0x2f, 0x4f, 0x6b, 0x36, 0x2b, 0x66, + 0x34, 0x31, 0x61, 0x2b, 0x76, 0x51, 0x4d, 0x43, 0x48, 0x4a, 0x4a, 0x72, 0x6a, 0x44, 0x58, 0x0a, + 0x32, 0x41, 0x79, 0x6e, 0x6d, 0x45, 0x2b, 0x6b, 0x45, 0x72, 0x59, 0x52, 0x32, 0x54, 0x6d, 0x61, + 0x74, 0x4c, 0x7a, 0x49, 0x72, 0x62, 0x4f, 0x4f, 0x32, 0x66, 0x56, 0x61, 0x46, 0x36, 0x6d, 0x2f, + 0x61, 0x6f, 0x6b, 0x33, 0x2b, 0x70, 0x54, 0x64, 0x2f, 0x39, 0x4b, 0x7a, 0x61, 0x68, 0x52, 0x48, + 0x4f, 0x34, 0x4e, 0x55, 0x34, 0x78, 0x6b, 0x58, 0x38, 0x4a, 0x74, 0x5a, 0x69, 0x30, 0x4b, 0x54, + 0x0a, 0x68, 0x56, 0x6e, 0x44, 0x2f, 0x6a, 0x6a, 0x51, 0x36, 0x62, 0x54, 0x33, 0x58, 0x6a, 0x35, + 0x4a, 0x53, 0x45, 0x38, 0x6f, 0x35, 0x72, 0x59, 0x71, 0x4a, 0x2f, 0x74, 0x4c, 0x55, 0x47, 0x2b, + 0x4d, 0x4d, 0x39, 0x4e, 0x31, 0x4c, 0x75, 0x32, 0x6a, 0x4f, 0x57, 0x6e, 0x6d, 0x4e, 0x78, 0x55, + 0x44, 0x72, 0x4b, 0x70, 0x56, 0x6b, 0x6c, 0x59, 0x76, 0x37, 0x59, 0x6e, 0x52, 0x61, 0x33, 0x41, + 0x64, 0x0a, 0x5a, 0x4d, 0x2b, 0x7a, 0x75, 0x34, 0x35, 0x56, 0x4e, 0x69, 0x76, 0x4b, 0x4f, 0x30, + 0x79, 0x59, 0x33, 0x7a, 0x35, 0x74, 0x73, 0x4a, 0x74, 0x48, 0x48, 0x34, 0x36, 0x4a, 0x69, 0x46, + 0x49, 0x79, 0x54, 0x68, 0x43, 0x67, 0x35, 0x42, 0x6c, 0x68, 0x70, 0x47, 0x51, 0x6a, 0x54, 0x41, + 0x73, 0x72, 0x68, 0x64, 0x49, 0x61, 0x47, 0x4d, 0x50, 0x64, 0x39, 0x49, 0x6d, 0x58, 0x73, 0x44, + 0x65, 0x2f, 0x0a, 0x4c, 0x35, 0x51, 0x79, 0x58, 0x41, 0x4f, 0x58, 0x62, 0x4e, 0x31, 0x33, 0x74, + 0x39, 0x64, 0x74, 0x72, 0x72, 0x76, 0x76, 0x70, 0x6b, 0x38, 0x48, 0x34, 0x5a, 0x48, 0x43, 0x73, + 0x61, 0x4f, 0x39, 0x53, 0x36, 0x36, 0x43, 0x43, 0x67, 0x4a, 0x7a, 0x59, 0x47, 0x55, 0x47, 0x34, + 0x75, 0x54, 0x35, 0x79, 0x61, 0x54, 0x61, 0x75, 0x54, 0x34, 0x50, 0x67, 0x77, 0x6b, 0x2f, 0x78, + 0x68, 0x32, 0x55, 0x0a, 0x74, 0x59, 0x52, 0x72, 0x4f, 0x39, 0x2b, 0x72, 0x51, 0x50, 0x4d, 0x62, + 0x4d, 0x45, 0x79, 0x33, 0x52, 0x74, 0x45, 0x67, 0x44, 0x79, 0x4c, 0x59, 0x70, 0x38, 0x6b, 0x69, + 0x6d, 0x44, 0x77, 0x71, 0x5a, 0x6d, 0x31, 0x45, 0x53, 0x72, 0x4a, 0x6e, 0x51, 0x6b, 0x7a, 0x71, + 0x76, 0x64, 0x78, 0x74, 0x46, 0x5a, 0x64, 0x54, 0x4b, 0x7a, 0x62, 0x32, 0x2b, 0x2b, 0x46, 0x6c, + 0x79, 0x5a, 0x45, 0x73, 0x0a, 0x56, 0x6d, 0x51, 0x73, 0x78, 0x70, 0x75, 0x4d, 0x4c, 0x67, 0x6a, + 0x73, 0x57, 0x35, 0x30, 0x49, 0x39, 0x2b, 0x46, 0x2f, 0x63, 0x68, 0x6a, 0x48, 0x37, 0x64, 0x77, + 0x65, 0x77, 0x37, 0x36, 0x39, 0x72, 0x50, 0x4c, 0x44, 0x62, 0x45, 0x79, 0x36, 0x4d, 0x6f, 0x74, + 0x4c, 0x62, 0x72, 0x67, 0x48, 0x69, 0x61, 0x66, 0x67, 0x44, 0x54, 0x61, 0x37, 0x6a, 0x76, 0x52, + 0x46, 0x55, 0x36, 0x54, 0x56, 0x0a, 0x78, 0x2f, 0x77, 0x68, 0x61, 0x6e, 0x50, 0x2f, 0x7a, 0x59, + 0x34, 0x65, 0x49, 0x4c, 0x72, 0x4f, 0x62, 0x43, 0x7a, 0x31, 0x4e, 0x50, 0x4c, 0x52, 0x6f, 0x35, + 0x70, 0x54, 0x6c, 0x6d, 0x49, 0x7a, 0x58, 0x36, 0x4d, 0x2f, 0x37, 0x79, 0x51, 0x45, 0x79, 0x34, + 0x34, 0x6a, 0x2f, 0x4a, 0x39, 0x53, 0x35, 0x62, 0x4d, 0x6a, 0x4e, 0x67, 0x2b, 0x75, 0x36, 0x72, + 0x43, 0x30, 0x54, 0x77, 0x53, 0x55, 0x0a, 0x6b, 0x64, 0x41, 0x68, 0x68, 0x64, 0x61, 0x48, 0x4e, + 0x75, 0x52, 0x4d, 0x35, 0x6a, 0x4f, 0x68, 0x6a, 0x57, 0x35, 0x4d, 0x46, 0x63, 0x71, 0x56, 0x36, + 0x4e, 0x35, 0x4d, 0x46, 0x6e, 0x34, 0x38, 0x69, 0x79, 0x52, 0x4b, 0x46, 0x54, 0x50, 0x78, 0x37, + 0x54, 0x4b, 0x68, 0x46, 0x38, 0x34, 0x6d, 0x64, 0x53, 0x2b, 0x56, 0x39, 0x2b, 0x43, 0x47, 0x52, + 0x51, 0x53, 0x65, 0x46, 0x70, 0x70, 0x38, 0x0a, 0x4a, 0x6e, 0x69, 0x49, 0x73, 0x6a, 0x71, 0x50, + 0x59, 0x6a, 0x68, 0x6e, 0x34, 0x6f, 0x74, 0x38, 0x52, 0x37, 0x6b, 0x64, 0x68, 0x79, 0x74, 0x38, + 0x31, 0x69, 0x31, 0x56, 0x53, 0x6e, 0x78, 0x33, 0x73, 0x70, 0x74, 0x33, 0x7a, 0x77, 0x30, 0x3d, + 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x58, 0x35, 0x30, 0x39, 0x20, 0x43, + 0x52, 0x4c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +#define APPLICATION_KEY_DER_LENGTH 1704 +UA_Byte APPLICATION_KEY_DER_DATA[1704] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, + 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x45, + 0x76, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, + 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, 0x42, 0x4b, 0x67, 0x77, + 0x67, 0x67, 0x53, 0x6b, 0x41, 0x67, 0x45, 0x41, 0x41, 0x6f, 0x49, 0x42, 0x41, 0x51, 0x44, 0x55, + 0x55, 0x6a, 0x55, 0x6c, 0x68, 0x39, 0x46, 0x73, 0x6f, 0x70, 0x49, 0x6d, 0x0a, 0x50, 0x4b, 0x5a, + 0x44, 0x59, 0x66, 0x46, 0x75, 0x76, 0x2f, 0x58, 0x70, 0x46, 0x68, 0x58, 0x55, 0x36, 0x63, 0x4f, + 0x74, 0x4f, 0x30, 0x6e, 0x75, 0x65, 0x79, 0x4d, 0x4b, 0x65, 0x5a, 0x4a, 0x39, 0x66, 0x50, 0x78, + 0x4b, 0x36, 0x52, 0x62, 0x4e, 0x49, 0x52, 0x65, 0x7a, 0x6e, 0x79, 0x78, 0x61, 0x44, 0x2b, 0x44, + 0x2f, 0x4d, 0x6c, 0x72, 0x46, 0x44, 0x54, 0x73, 0x7a, 0x44, 0x66, 0x71, 0x4b, 0x0a, 0x4c, 0x61, + 0x50, 0x70, 0x4d, 0x42, 0x49, 0x52, 0x44, 0x48, 0x76, 0x32, 0x51, 0x52, 0x68, 0x59, 0x73, 0x52, + 0x49, 0x57, 0x30, 0x61, 0x69, 0x46, 0x70, 0x66, 0x70, 0x38, 0x38, 0x30, 0x68, 0x53, 0x74, 0x42, + 0x41, 0x69, 0x52, 0x2f, 0x43, 0x59, 0x4f, 0x73, 0x37, 0x6e, 0x34, 0x34, 0x5a, 0x66, 0x73, 0x50, + 0x6f, 0x75, 0x75, 0x4f, 0x34, 0x66, 0x79, 0x33, 0x6a, 0x5a, 0x6f, 0x37, 0x79, 0x75, 0x0a, 0x35, + 0x6e, 0x65, 0x4c, 0x4f, 0x47, 0x46, 0x32, 0x72, 0x75, 0x73, 0x72, 0x7a, 0x75, 0x42, 0x35, 0x62, + 0x45, 0x6f, 0x71, 0x44, 0x58, 0x6c, 0x67, 0x62, 0x7a, 0x35, 0x74, 0x31, 0x49, 0x4f, 0x54, 0x58, + 0x49, 0x4d, 0x62, 0x62, 0x52, 0x52, 0x41, 0x4f, 0x39, 0x63, 0x52, 0x54, 0x50, 0x48, 0x75, 0x72, + 0x4c, 0x67, 0x53, 0x73, 0x45, 0x63, 0x37, 0x6e, 0x58, 0x6e, 0x35, 0x79, 0x43, 0x59, 0x37, 0x0a, + 0x68, 0x54, 0x2f, 0x34, 0x6c, 0x2f, 0x50, 0x61, 0x7a, 0x65, 0x70, 0x68, 0x70, 0x4e, 0x77, 0x6b, + 0x33, 0x44, 0x72, 0x31, 0x4d, 0x4b, 0x53, 0x4a, 0x70, 0x32, 0x42, 0x59, 0x69, 0x34, 0x73, 0x45, + 0x7a, 0x6a, 0x77, 0x4b, 0x69, 0x44, 0x4f, 0x41, 0x4b, 0x65, 0x67, 0x58, 0x6a, 0x52, 0x6f, 0x4d, + 0x6a, 0x79, 0x42, 0x64, 0x61, 0x6b, 0x56, 0x63, 0x67, 0x62, 0x35, 0x35, 0x6d, 0x77, 0x64, 0x7a, + 0x0a, 0x48, 0x30, 0x65, 0x36, 0x78, 0x64, 0x70, 0x64, 0x71, 0x45, 0x79, 0x49, 0x42, 0x6b, 0x4f, + 0x48, 0x39, 0x65, 0x51, 0x67, 0x32, 0x32, 0x73, 0x2b, 0x75, 0x68, 0x70, 0x39, 0x38, 0x56, 0x71, + 0x46, 0x41, 0x35, 0x7a, 0x6b, 0x52, 0x61, 0x32, 0x73, 0x74, 0x74, 0x35, 0x58, 0x36, 0x62, 0x76, + 0x53, 0x37, 0x4d, 0x62, 0x33, 0x47, 0x31, 0x42, 0x54, 0x66, 0x47, 0x4e, 0x4f, 0x7a, 0x4f, 0x5a, + 0x55, 0x0a, 0x42, 0x6f, 0x56, 0x4a, 0x2f, 0x30, 0x74, 0x50, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, + 0x45, 0x43, 0x67, 0x67, 0x45, 0x41, 0x55, 0x52, 0x4e, 0x52, 0x4d, 0x78, 0x4d, 0x68, 0x62, 0x39, + 0x50, 0x47, 0x62, 0x69, 0x35, 0x7a, 0x71, 0x4d, 0x42, 0x69, 0x51, 0x70, 0x47, 0x76, 0x74, 0x41, + 0x46, 0x59, 0x64, 0x64, 0x53, 0x4d, 0x41, 0x58, 0x37, 0x6c, 0x31, 0x4e, 0x69, 0x56, 0x67, 0x56, + 0x37, 0x36, 0x0a, 0x42, 0x73, 0x77, 0x75, 0x78, 0x4f, 0x59, 0x72, 0x37, 0x45, 0x6d, 0x71, 0x4e, + 0x4d, 0x39, 0x66, 0x7a, 0x73, 0x5a, 0x49, 0x65, 0x76, 0x70, 0x39, 0x2b, 0x63, 0x66, 0x37, 0x4a, + 0x70, 0x77, 0x38, 0x59, 0x76, 0x35, 0x5a, 0x6e, 0x47, 0x5a, 0x63, 0x52, 0x38, 0x46, 0x57, 0x4a, + 0x71, 0x73, 0x6c, 0x77, 0x6c, 0x78, 0x66, 0x56, 0x58, 0x4a, 0x61, 0x34, 0x53, 0x6f, 0x48, 0x74, + 0x43, 0x58, 0x73, 0x0a, 0x4a, 0x4a, 0x53, 0x59, 0x6f, 0x70, 0x61, 0x49, 0x38, 0x34, 0x42, 0x6c, + 0x57, 0x4e, 0x77, 0x6a, 0x69, 0x43, 0x2f, 0x61, 0x34, 0x50, 0x4f, 0x43, 0x44, 0x6f, 0x63, 0x53, + 0x6a, 0x7a, 0x7a, 0x38, 0x68, 0x47, 0x63, 0x43, 0x47, 0x42, 0x6e, 0x2f, 0x38, 0x61, 0x4f, 0x4b, + 0x72, 0x74, 0x42, 0x52, 0x48, 0x46, 0x79, 0x7a, 0x46, 0x30, 0x72, 0x4d, 0x34, 0x66, 0x75, 0x6f, + 0x77, 0x61, 0x51, 0x57, 0x0a, 0x47, 0x71, 0x42, 0x77, 0x36, 0x43, 0x46, 0x41, 0x4a, 0x6a, 0x46, + 0x33, 0x64, 0x4e, 0x2f, 0x61, 0x4d, 0x66, 0x7a, 0x71, 0x35, 0x37, 0x42, 0x32, 0x67, 0x69, 0x67, + 0x49, 0x32, 0x36, 0x41, 0x4b, 0x39, 0x70, 0x62, 0x32, 0x5a, 0x4c, 0x74, 0x4f, 0x45, 0x59, 0x49, + 0x52, 0x2b, 0x46, 0x51, 0x56, 0x4b, 0x33, 0x57, 0x6f, 0x36, 0x75, 0x66, 0x2f, 0x48, 0x67, 0x59, + 0x4a, 0x47, 0x38, 0x2b, 0x75, 0x0a, 0x43, 0x33, 0x2f, 0x67, 0x70, 0x4d, 0x5a, 0x49, 0x58, 0x6a, + 0x67, 0x6b, 0x66, 0x30, 0x78, 0x74, 0x32, 0x41, 0x37, 0x39, 0x2f, 0x54, 0x74, 0x30, 0x37, 0x69, + 0x39, 0x62, 0x73, 0x5a, 0x4b, 0x54, 0x6a, 0x67, 0x78, 0x76, 0x2b, 0x73, 0x41, 0x70, 0x32, 0x69, + 0x79, 0x74, 0x6a, 0x6f, 0x6e, 0x34, 0x65, 0x74, 0x41, 0x4d, 0x49, 0x49, 0x49, 0x70, 0x58, 0x36, + 0x4c, 0x46, 0x75, 0x68, 0x6f, 0x68, 0x0a, 0x52, 0x54, 0x76, 0x6e, 0x45, 0x57, 0x2f, 0x4f, 0x5a, + 0x37, 0x4a, 0x70, 0x44, 0x32, 0x53, 0x35, 0x77, 0x50, 0x37, 0x4d, 0x54, 0x36, 0x48, 0x4c, 0x2b, + 0x72, 0x35, 0x50, 0x6c, 0x64, 0x52, 0x47, 0x39, 0x35, 0x63, 0x61, 0x39, 0x55, 0x47, 0x5a, 0x69, + 0x51, 0x4b, 0x42, 0x67, 0x51, 0x44, 0x65, 0x72, 0x77, 0x66, 0x59, 0x63, 0x72, 0x37, 0x30, 0x75, + 0x51, 0x59, 0x55, 0x4d, 0x74, 0x32, 0x53, 0x0a, 0x66, 0x51, 0x54, 0x46, 0x31, 0x77, 0x39, 0x68, + 0x36, 0x66, 0x36, 0x75, 0x6d, 0x41, 0x77, 0x31, 0x45, 0x51, 0x31, 0x52, 0x42, 0x35, 0x71, 0x38, + 0x6b, 0x6a, 0x6d, 0x61, 0x41, 0x59, 0x62, 0x2b, 0x32, 0x2b, 0x75, 0x69, 0x59, 0x70, 0x4c, 0x53, + 0x4b, 0x64, 0x56, 0x67, 0x4a, 0x66, 0x44, 0x38, 0x67, 0x37, 0x49, 0x39, 0x32, 0x64, 0x76, 0x4f, + 0x78, 0x5a, 0x39, 0x66, 0x59, 0x6a, 0x73, 0x59, 0x0a, 0x6a, 0x56, 0x4a, 0x33, 0x6e, 0x68, 0x59, + 0x42, 0x44, 0x79, 0x6a, 0x73, 0x6c, 0x2b, 0x71, 0x2b, 0x73, 0x78, 0x68, 0x56, 0x48, 0x61, 0x37, + 0x44, 0x2f, 0x61, 0x44, 0x31, 0x66, 0x47, 0x4f, 0x48, 0x4a, 0x2b, 0x79, 0x4c, 0x44, 0x79, 0x75, + 0x49, 0x49, 0x41, 0x47, 0x4d, 0x79, 0x51, 0x31, 0x47, 0x51, 0x36, 0x30, 0x37, 0x48, 0x47, 0x30, + 0x56, 0x38, 0x61, 0x50, 0x69, 0x49, 0x34, 0x59, 0x47, 0x0a, 0x48, 0x37, 0x6b, 0x49, 0x49, 0x6b, + 0x31, 0x77, 0x37, 0x39, 0x52, 0x74, 0x46, 0x71, 0x67, 0x39, 0x6b, 0x48, 0x34, 0x68, 0x30, 0x4e, + 0x77, 0x48, 0x46, 0x77, 0x4b, 0x42, 0x67, 0x51, 0x44, 0x30, 0x46, 0x6b, 0x66, 0x2f, 0x4f, 0x64, + 0x74, 0x48, 0x57, 0x6a, 0x6c, 0x72, 0x2f, 0x76, 0x54, 0x77, 0x68, 0x73, 0x4e, 0x36, 0x37, 0x66, + 0x54, 0x74, 0x2f, 0x4c, 0x62, 0x6d, 0x65, 0x53, 0x41, 0x45, 0x0a, 0x57, 0x5a, 0x39, 0x58, 0x79, + 0x74, 0x79, 0x4c, 0x64, 0x5a, 0x76, 0x46, 0x67, 0x2b, 0x64, 0x39, 0x4f, 0x55, 0x65, 0x31, 0x42, + 0x54, 0x31, 0x61, 0x41, 0x31, 0x56, 0x50, 0x72, 0x59, 0x65, 0x4c, 0x35, 0x69, 0x6d, 0x30, 0x52, + 0x6c, 0x78, 0x67, 0x57, 0x47, 0x53, 0x36, 0x65, 0x78, 0x67, 0x71, 0x6d, 0x73, 0x71, 0x2b, 0x41, + 0x79, 0x6c, 0x32, 0x38, 0x6f, 0x41, 0x57, 0x56, 0x2f, 0x73, 0x46, 0x0a, 0x4a, 0x45, 0x47, 0x71, + 0x52, 0x66, 0x6c, 0x48, 0x41, 0x32, 0x4f, 0x77, 0x72, 0x31, 0x62, 0x53, 0x63, 0x55, 0x6e, 0x55, + 0x6f, 0x76, 0x57, 0x54, 0x79, 0x72, 0x4c, 0x70, 0x30, 0x4a, 0x31, 0x52, 0x51, 0x57, 0x6d, 0x52, + 0x7a, 0x4d, 0x53, 0x4d, 0x71, 0x74, 0x34, 0x48, 0x65, 0x58, 0x6f, 0x67, 0x57, 0x4a, 0x6b, 0x73, + 0x62, 0x6e, 0x6f, 0x4c, 0x6d, 0x49, 0x39, 0x35, 0x56, 0x64, 0x69, 0x64, 0x0a, 0x58, 0x70, 0x4a, + 0x43, 0x64, 0x57, 0x79, 0x41, 0x69, 0x51, 0x4b, 0x42, 0x67, 0x46, 0x68, 0x4b, 0x37, 0x41, 0x42, + 0x74, 0x56, 0x72, 0x74, 0x76, 0x6c, 0x54, 0x4a, 0x7a, 0x44, 0x4a, 0x6c, 0x6c, 0x69, 0x6e, 0x76, + 0x72, 0x44, 0x6f, 0x56, 0x54, 0x49, 0x78, 0x45, 0x55, 0x35, 0x6c, 0x6f, 0x77, 0x48, 0x61, 0x69, + 0x51, 0x4c, 0x46, 0x45, 0x79, 0x5a, 0x54, 0x5a, 0x6a, 0x2f, 0x71, 0x4f, 0x55, 0x0a, 0x6a, 0x54, + 0x52, 0x41, 0x67, 0x31, 0x68, 0x6a, 0x44, 0x2b, 0x42, 0x6b, 0x69, 0x73, 0x32, 0x45, 0x5a, 0x69, + 0x72, 0x52, 0x38, 0x36, 0x35, 0x6a, 0x65, 0x78, 0x4a, 0x31, 0x76, 0x31, 0x71, 0x33, 0x78, 0x67, + 0x66, 0x35, 0x6e, 0x56, 0x33, 0x6b, 0x4a, 0x65, 0x54, 0x52, 0x51, 0x31, 0x6c, 0x44, 0x5a, 0x35, + 0x56, 0x77, 0x42, 0x48, 0x68, 0x66, 0x57, 0x75, 0x2b, 0x61, 0x31, 0x31, 0x65, 0x69, 0x0a, 0x67, + 0x38, 0x36, 0x4c, 0x51, 0x45, 0x5a, 0x6a, 0x38, 0x6c, 0x6c, 0x67, 0x36, 0x69, 0x74, 0x2b, 0x37, + 0x2f, 0x4f, 0x74, 0x44, 0x4b, 0x2b, 0x54, 0x74, 0x4e, 0x67, 0x59, 0x48, 0x36, 0x37, 0x54, 0x36, + 0x79, 0x69, 0x48, 0x65, 0x55, 0x38, 0x62, 0x4f, 0x49, 0x33, 0x63, 0x57, 0x75, 0x36, 0x32, 0x47, + 0x4e, 0x7a, 0x4e, 0x6c, 0x45, 0x41, 0x58, 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4d, 0x42, 0x58, 0x0a, + 0x43, 0x6e, 0x62, 0x78, 0x5a, 0x58, 0x7a, 0x4e, 0x65, 0x54, 0x42, 0x44, 0x34, 0x55, 0x6e, 0x6b, + 0x4f, 0x41, 0x67, 0x58, 0x6d, 0x51, 0x6b, 0x73, 0x4f, 0x67, 0x68, 0x56, 0x62, 0x45, 0x68, 0x68, + 0x51, 0x7a, 0x49, 0x51, 0x4e, 0x6b, 0x68, 0x69, 0x37, 0x64, 0x50, 0x77, 0x42, 0x43, 0x74, 0x6d, + 0x52, 0x72, 0x34, 0x37, 0x6d, 0x63, 0x50, 0x6a, 0x6d, 0x6f, 0x64, 0x46, 0x36, 0x2b, 0x6a, 0x75, + 0x0a, 0x2f, 0x76, 0x41, 0x43, 0x2f, 0x65, 0x6f, 0x68, 0x33, 0x59, 0x59, 0x68, 0x56, 0x38, 0x4c, + 0x43, 0x35, 0x58, 0x35, 0x6a, 0x79, 0x58, 0x6e, 0x6b, 0x7a, 0x39, 0x42, 0x4c, 0x6c, 0x67, 0x2f, + 0x51, 0x4b, 0x54, 0x70, 0x2f, 0x46, 0x31, 0x62, 0x42, 0x4d, 0x66, 0x35, 0x5a, 0x76, 0x4f, 0x58, + 0x70, 0x78, 0x63, 0x38, 0x63, 0x64, 0x72, 0x33, 0x32, 0x58, 0x5a, 0x50, 0x6f, 0x41, 0x76, 0x2b, + 0x7a, 0x0a, 0x74, 0x76, 0x66, 0x67, 0x54, 0x77, 0x57, 0x31, 0x34, 0x32, 0x34, 0x71, 0x61, 0x48, + 0x55, 0x79, 0x75, 0x38, 0x6b, 0x4b, 0x61, 0x58, 0x76, 0x58, 0x78, 0x54, 0x39, 0x4d, 0x79, 0x58, + 0x77, 0x41, 0x75, 0x4f, 0x70, 0x4c, 0x30, 0x36, 0x74, 0x5a, 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4e, + 0x75, 0x61, 0x68, 0x64, 0x65, 0x75, 0x61, 0x51, 0x6d, 0x6d, 0x6f, 0x6f, 0x51, 0x72, 0x70, 0x38, + 0x52, 0x45, 0x0a, 0x46, 0x6a, 0x63, 0x53, 0x6e, 0x7a, 0x64, 0x43, 0x41, 0x64, 0x50, 0x37, 0x79, + 0x74, 0x63, 0x58, 0x71, 0x77, 0x51, 0x62, 0x4c, 0x53, 0x64, 0x76, 0x48, 0x54, 0x73, 0x54, 0x57, + 0x71, 0x64, 0x6b, 0x67, 0x34, 0x55, 0x70, 0x51, 0x5a, 0x4c, 0x4d, 0x4f, 0x61, 0x37, 0x32, 0x4b, + 0x6b, 0x2b, 0x47, 0x42, 0x77, 0x67, 0x45, 0x2f, 0x6c, 0x39, 0x4f, 0x6f, 0x61, 0x32, 0x37, 0x65, + 0x69, 0x79, 0x45, 0x0a, 0x38, 0x4f, 0x75, 0x43, 0x65, 0x55, 0x41, 0x32, 0x37, 0x57, 0x6b, 0x55, + 0x54, 0x31, 0x31, 0x6f, 0x7a, 0x58, 0x65, 0x43, 0x72, 0x61, 0x55, 0x71, 0x4f, 0x55, 0x43, 0x4e, + 0x6e, 0x33, 0x37, 0x4a, 0x46, 0x30, 0x43, 0x31, 0x77, 0x51, 0x63, 0x4d, 0x7a, 0x76, 0x65, 0x69, + 0x69, 0x79, 0x45, 0x58, 0x33, 0x61, 0x67, 0x64, 0x51, 0x6f, 0x57, 0x67, 0x34, 0x55, 0x52, 0x67, + 0x37, 0x36, 0x79, 0x4d, 0x0a, 0x30, 0x48, 0x2f, 0x48, 0x45, 0x77, 0x73, 0x33, 0x46, 0x45, 0x56, + 0x55, 0x55, 0x35, 0x6a, 0x6f, 0x43, 0x69, 0x79, 0x51, 0x2f, 0x65, 0x65, 0x30, 0x0a, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, + 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a +}; + +#define APPLICATION_CERT_DER_LENGTH 1732 +UA_Byte APPLICATION_CERT_DER_DATA[1732] = { + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, + 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x45, + 0x30, 0x6a, 0x43, 0x43, 0x41, 0x72, 0x71, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, + 0x43, 0x49, 0x69, 0x47, 0x4f, 0x65, 0x66, 0x54, 0x65, 0x4c, 0x4b, 0x4a, 0x70, 0x50, 0x69, 0x4c, + 0x39, 0x6e, 0x45, 0x41, 0x77, 0x33, 0x5a, 0x34, 0x44, 0x4b, 0x45, 0x77, 0x44, 0x51, 0x59, 0x4a, + 0x4b, 0x6f, 0x5a, 0x49, 0x68, 0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x4c, 0x0a, 0x42, 0x51, 0x41, + 0x77, 0x62, 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, + 0x43, 0x52, 0x45, 0x55, 0x78, 0x44, 0x6a, 0x41, 0x4d, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, + 0x4d, 0x42, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x51, 0x30, 0x77, 0x43, 0x77, 0x59, + 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x52, 0x44, 0x61, 0x58, 0x52, 0x35, 0x0a, 0x4d, 0x52, + 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x41, 0x78, 0x50, 0x63, 0x6d, + 0x64, 0x68, 0x62, 0x6d, 0x6c, 0x36, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, 0x78, 0x45, 0x44, + 0x41, 0x4f, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x73, 0x4d, 0x42, 0x30, 0x39, 0x79, 0x5a, 0x31, + 0x56, 0x75, 0x61, 0x58, 0x51, 0x78, 0x46, 0x7a, 0x41, 0x56, 0x42, 0x67, 0x4e, 0x56, 0x0a, 0x42, + 0x41, 0x4d, 0x4d, 0x44, 0x6b, 0x6c, 0x75, 0x64, 0x47, 0x56, 0x79, 0x62, 0x57, 0x56, 0x6b, 0x61, + 0x57, 0x46, 0x30, 0x5a, 0x55, 0x4e, 0x42, 0x4d, 0x42, 0x34, 0x58, 0x44, 0x54, 0x49, 0x30, 0x4d, + 0x44, 0x6b, 0x78, 0x4d, 0x54, 0x45, 0x30, 0x4d, 0x44, 0x41, 0x31, 0x4e, 0x46, 0x6f, 0x58, 0x44, + 0x54, 0x4d, 0x30, 0x4d, 0x44, 0x6b, 0x77, 0x4f, 0x54, 0x45, 0x30, 0x4d, 0x44, 0x41, 0x31, 0x0a, + 0x4e, 0x46, 0x6f, 0x77, 0x61, 0x7a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, + 0x42, 0x68, 0x4d, 0x43, 0x52, 0x45, 0x55, 0x78, 0x44, 0x6a, 0x41, 0x4d, 0x42, 0x67, 0x4e, 0x56, + 0x42, 0x41, 0x67, 0x4d, 0x42, 0x56, 0x4e, 0x30, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x51, 0x30, 0x77, + 0x43, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x52, 0x44, 0x61, 0x58, 0x52, 0x35, + 0x0a, 0x4d, 0x52, 0x55, 0x77, 0x45, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x4b, 0x44, 0x41, 0x78, + 0x50, 0x63, 0x6d, 0x64, 0x68, 0x62, 0x6d, 0x6c, 0x36, 0x59, 0x58, 0x52, 0x70, 0x62, 0x32, 0x34, + 0x78, 0x45, 0x44, 0x41, 0x4f, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x73, 0x4d, 0x42, 0x30, 0x39, + 0x79, 0x5a, 0x31, 0x56, 0x75, 0x61, 0x58, 0x51, 0x78, 0x46, 0x44, 0x41, 0x53, 0x42, 0x67, 0x4e, + 0x56, 0x0a, 0x42, 0x41, 0x4d, 0x4d, 0x43, 0x30, 0x46, 0x77, 0x63, 0x47, 0x78, 0x70, 0x59, 0x32, + 0x46, 0x30, 0x61, 0x57, 0x39, 0x75, 0x4d, 0x49, 0x49, 0x42, 0x49, 0x6a, 0x41, 0x4e, 0x42, 0x67, + 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, + 0x4f, 0x43, 0x41, 0x51, 0x38, 0x41, 0x4d, 0x49, 0x49, 0x42, 0x43, 0x67, 0x4b, 0x43, 0x41, 0x51, + 0x45, 0x41, 0x0a, 0x31, 0x46, 0x49, 0x31, 0x4a, 0x59, 0x66, 0x52, 0x62, 0x4b, 0x4b, 0x53, 0x4a, + 0x6a, 0x79, 0x6d, 0x51, 0x32, 0x48, 0x78, 0x62, 0x72, 0x2f, 0x31, 0x36, 0x52, 0x59, 0x56, 0x31, + 0x4f, 0x6e, 0x44, 0x72, 0x54, 0x74, 0x4a, 0x37, 0x6e, 0x73, 0x6a, 0x43, 0x6e, 0x6d, 0x53, 0x66, + 0x58, 0x7a, 0x38, 0x53, 0x75, 0x6b, 0x57, 0x7a, 0x53, 0x45, 0x58, 0x73, 0x35, 0x38, 0x73, 0x57, + 0x67, 0x2f, 0x67, 0x0a, 0x2f, 0x7a, 0x4a, 0x61, 0x78, 0x51, 0x30, 0x37, 0x4d, 0x77, 0x33, 0x36, + 0x69, 0x69, 0x32, 0x6a, 0x36, 0x54, 0x41, 0x53, 0x45, 0x51, 0x78, 0x37, 0x39, 0x6b, 0x45, 0x59, + 0x57, 0x4c, 0x45, 0x53, 0x46, 0x74, 0x47, 0x6f, 0x68, 0x61, 0x58, 0x36, 0x66, 0x50, 0x4e, 0x49, + 0x55, 0x72, 0x51, 0x51, 0x49, 0x6b, 0x66, 0x77, 0x6d, 0x44, 0x72, 0x4f, 0x35, 0x2b, 0x4f, 0x47, + 0x58, 0x37, 0x44, 0x36, 0x0a, 0x4c, 0x72, 0x6a, 0x75, 0x48, 0x38, 0x74, 0x34, 0x32, 0x61, 0x4f, + 0x38, 0x72, 0x75, 0x5a, 0x33, 0x69, 0x7a, 0x68, 0x68, 0x64, 0x71, 0x37, 0x72, 0x4b, 0x38, 0x37, + 0x67, 0x65, 0x57, 0x78, 0x4b, 0x4b, 0x67, 0x31, 0x35, 0x59, 0x47, 0x38, 0x2b, 0x62, 0x64, 0x53, + 0x44, 0x6b, 0x31, 0x79, 0x44, 0x47, 0x32, 0x30, 0x55, 0x51, 0x44, 0x76, 0x58, 0x45, 0x55, 0x7a, + 0x78, 0x37, 0x71, 0x79, 0x34, 0x0a, 0x45, 0x72, 0x42, 0x48, 0x4f, 0x35, 0x31, 0x35, 0x2b, 0x63, + 0x67, 0x6d, 0x4f, 0x34, 0x55, 0x2f, 0x2b, 0x4a, 0x66, 0x7a, 0x32, 0x73, 0x33, 0x71, 0x59, 0x61, + 0x54, 0x63, 0x4a, 0x4e, 0x77, 0x36, 0x39, 0x54, 0x43, 0x6b, 0x69, 0x61, 0x64, 0x67, 0x57, 0x49, + 0x75, 0x4c, 0x42, 0x4d, 0x34, 0x38, 0x43, 0x6f, 0x67, 0x7a, 0x67, 0x43, 0x6e, 0x6f, 0x46, 0x34, + 0x30, 0x61, 0x44, 0x49, 0x38, 0x67, 0x0a, 0x58, 0x57, 0x70, 0x46, 0x58, 0x49, 0x47, 0x2b, 0x65, + 0x5a, 0x73, 0x48, 0x63, 0x78, 0x39, 0x48, 0x75, 0x73, 0x58, 0x61, 0x58, 0x61, 0x68, 0x4d, 0x69, + 0x41, 0x5a, 0x44, 0x68, 0x2f, 0x58, 0x6b, 0x49, 0x4e, 0x74, 0x72, 0x50, 0x72, 0x6f, 0x61, 0x66, + 0x66, 0x46, 0x61, 0x68, 0x51, 0x4f, 0x63, 0x35, 0x45, 0x57, 0x74, 0x72, 0x4c, 0x62, 0x65, 0x56, + 0x2b, 0x6d, 0x37, 0x30, 0x75, 0x7a, 0x47, 0x0a, 0x39, 0x78, 0x74, 0x51, 0x55, 0x33, 0x78, 0x6a, + 0x54, 0x73, 0x7a, 0x6d, 0x56, 0x41, 0x61, 0x46, 0x53, 0x66, 0x39, 0x4c, 0x54, 0x77, 0x49, 0x44, + 0x41, 0x51, 0x41, 0x42, 0x6f, 0x32, 0x73, 0x77, 0x61, 0x54, 0x41, 0x6e, 0x42, 0x67, 0x4e, 0x56, + 0x48, 0x52, 0x45, 0x45, 0x49, 0x44, 0x41, 0x65, 0x68, 0x68, 0x78, 0x31, 0x63, 0x6d, 0x34, 0x36, + 0x64, 0x57, 0x35, 0x6a, 0x62, 0x32, 0x35, 0x6d, 0x0a, 0x61, 0x57, 0x64, 0x31, 0x63, 0x6d, 0x56, + 0x6b, 0x4f, 0x6d, 0x46, 0x77, 0x63, 0x47, 0x78, 0x70, 0x59, 0x32, 0x46, 0x30, 0x61, 0x57, 0x39, + 0x75, 0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x53, + 0x4e, 0x74, 0x2f, 0x68, 0x36, 0x7a, 0x4f, 0x62, 0x54, 0x76, 0x46, 0x33, 0x7a, 0x67, 0x75, 0x65, + 0x5a, 0x75, 0x44, 0x75, 0x38, 0x51, 0x43, 0x4a, 0x30, 0x0a, 0x6f, 0x7a, 0x41, 0x66, 0x42, 0x67, + 0x4e, 0x56, 0x48, 0x53, 0x4d, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x52, 0x6c, 0x76, 0x43, + 0x32, 0x55, 0x61, 0x31, 0x32, 0x64, 0x34, 0x59, 0x51, 0x31, 0x4f, 0x51, 0x79, 0x2b, 0x32, 0x43, + 0x76, 0x4c, 0x6e, 0x4c, 0x47, 0x72, 0x41, 0x44, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, + 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x0a, 0x41, 0x41, 0x4f, 0x43, 0x41, + 0x67, 0x45, 0x41, 0x72, 0x62, 0x55, 0x4c, 0x61, 0x54, 0x44, 0x46, 0x39, 0x69, 0x30, 0x70, 0x66, + 0x34, 0x7a, 0x6d, 0x62, 0x55, 0x53, 0x69, 0x64, 0x34, 0x6f, 0x57, 0x7a, 0x6e, 0x45, 0x42, 0x77, + 0x55, 0x5a, 0x69, 0x6e, 0x37, 0x59, 0x69, 0x54, 0x76, 0x67, 0x38, 0x73, 0x34, 0x41, 0x31, 0x43, + 0x42, 0x76, 0x2f, 0x31, 0x75, 0x72, 0x75, 0x41, 0x62, 0x39, 0x6d, 0x0a, 0x4a, 0x52, 0x52, 0x59, + 0x35, 0x37, 0x61, 0x32, 0x65, 0x6c, 0x7a, 0x68, 0x31, 0x37, 0x45, 0x76, 0x51, 0x39, 0x72, 0x30, + 0x4a, 0x48, 0x6e, 0x49, 0x66, 0x73, 0x35, 0x41, 0x56, 0x68, 0x57, 0x2f, 0x4e, 0x45, 0x62, 0x6e, + 0x75, 0x5a, 0x73, 0x39, 0x59, 0x6a, 0x53, 0x6c, 0x6a, 0x55, 0x58, 0x74, 0x44, 0x64, 0x47, 0x63, + 0x6b, 0x6f, 0x48, 0x61, 0x34, 0x53, 0x4d, 0x55, 0x44, 0x44, 0x2f, 0x44, 0x0a, 0x76, 0x78, 0x4e, + 0x46, 0x44, 0x31, 0x6f, 0x72, 0x67, 0x2b, 0x79, 0x39, 0x75, 0x2b, 0x2f, 0x6b, 0x64, 0x52, 0x4d, + 0x64, 0x67, 0x66, 0x6d, 0x5a, 0x45, 0x69, 0x32, 0x59, 0x55, 0x62, 0x57, 0x68, 0x51, 0x53, 0x37, + 0x78, 0x34, 0x34, 0x31, 0x57, 0x73, 0x52, 0x30, 0x33, 0x32, 0x66, 0x4d, 0x54, 0x42, 0x44, 0x2b, + 0x64, 0x6b, 0x33, 0x38, 0x77, 0x42, 0x31, 0x4e, 0x2b, 0x42, 0x6e, 0x56, 0x54, 0x0a, 0x54, 0x43, + 0x50, 0x4c, 0x68, 0x43, 0x74, 0x6c, 0x76, 0x6d, 0x54, 0x46, 0x68, 0x34, 0x47, 0x48, 0x38, 0x71, + 0x48, 0x79, 0x57, 0x79, 0x77, 0x47, 0x48, 0x6a, 0x76, 0x38, 0x6e, 0x45, 0x45, 0x65, 0x70, 0x47, + 0x72, 0x68, 0x49, 0x49, 0x56, 0x66, 0x7a, 0x53, 0x57, 0x38, 0x51, 0x66, 0x53, 0x66, 0x4b, 0x6c, + 0x6a, 0x4d, 0x30, 0x36, 0x62, 0x76, 0x71, 0x4d, 0x58, 0x31, 0x2f, 0x46, 0x6b, 0x70, 0x0a, 0x38, + 0x76, 0x48, 0x41, 0x4e, 0x53, 0x67, 0x54, 0x69, 0x57, 0x2f, 0x4b, 0x58, 0x59, 0x7a, 0x33, 0x36, + 0x67, 0x71, 0x59, 0x57, 0x70, 0x44, 0x2f, 0x32, 0x41, 0x74, 0x57, 0x35, 0x75, 0x44, 0x4e, 0x58, + 0x56, 0x62, 0x76, 0x70, 0x5a, 0x48, 0x4b, 0x57, 0x59, 0x76, 0x34, 0x30, 0x67, 0x63, 0x73, 0x2f, + 0x59, 0x6b, 0x37, 0x66, 0x6a, 0x33, 0x38, 0x44, 0x65, 0x76, 0x4b, 0x46, 0x57, 0x35, 0x49, 0x0a, + 0x65, 0x71, 0x6c, 0x43, 0x55, 0x59, 0x6f, 0x50, 0x30, 0x2f, 0x41, 0x37, 0x47, 0x77, 0x43, 0x45, + 0x63, 0x58, 0x4a, 0x2f, 0x6b, 0x4a, 0x70, 0x5a, 0x50, 0x30, 0x45, 0x6d, 0x45, 0x37, 0x41, 0x51, + 0x6a, 0x6c, 0x61, 0x46, 0x6e, 0x44, 0x41, 0x51, 0x54, 0x71, 0x50, 0x57, 0x57, 0x2f, 0x4b, 0x72, + 0x73, 0x68, 0x2f, 0x61, 0x42, 0x65, 0x39, 0x2b, 0x5a, 0x41, 0x54, 0x46, 0x71, 0x50, 0x4f, 0x72, + 0x0a, 0x38, 0x32, 0x43, 0x43, 0x6d, 0x63, 0x4f, 0x59, 0x73, 0x32, 0x45, 0x2f, 0x2f, 0x6d, 0x77, + 0x30, 0x76, 0x59, 0x6d, 0x4c, 0x78, 0x68, 0x38, 0x4f, 0x61, 0x50, 0x37, 0x30, 0x62, 0x63, 0x4f, + 0x65, 0x65, 0x37, 0x64, 0x67, 0x51, 0x66, 0x4c, 0x53, 0x77, 0x75, 0x68, 0x71, 0x51, 0x44, 0x79, + 0x61, 0x44, 0x57, 0x2b, 0x67, 0x77, 0x75, 0x61, 0x61, 0x2f, 0x79, 0x7a, 0x71, 0x6b, 0x63, 0x4f, + 0x6c, 0x0a, 0x6c, 0x44, 0x30, 0x2f, 0x73, 0x51, 0x6e, 0x59, 0x68, 0x6a, 0x50, 0x53, 0x72, 0x62, + 0x49, 0x33, 0x36, 0x41, 0x54, 0x4a, 0x2f, 0x73, 0x36, 0x34, 0x4f, 0x41, 0x6e, 0x6d, 0x74, 0x70, + 0x4a, 0x53, 0x6d, 0x68, 0x51, 0x50, 0x67, 0x4a, 0x59, 0x63, 0x5a, 0x6a, 0x65, 0x32, 0x49, 0x6c, + 0x48, 0x42, 0x36, 0x77, 0x34, 0x38, 0x4c, 0x5a, 0x48, 0x34, 0x57, 0x79, 0x57, 0x4e, 0x30, 0x61, + 0x52, 0x4b, 0x0a, 0x32, 0x36, 0x70, 0x43, 0x53, 0x67, 0x49, 0x6a, 0x58, 0x74, 0x64, 0x7a, 0x43, + 0x47, 0x71, 0x48, 0x57, 0x53, 0x6c, 0x72, 0x55, 0x57, 0x59, 0x70, 0x6c, 0x77, 0x71, 0x46, 0x73, + 0x59, 0x33, 0x77, 0x6b, 0x34, 0x35, 0x6c, 0x58, 0x66, 0x53, 0x32, 0x30, 0x62, 0x6c, 0x45, 0x4d, + 0x30, 0x47, 0x41, 0x55, 0x7a, 0x2f, 0x56, 0x58, 0x33, 0x78, 0x58, 0x35, 0x6d, 0x51, 0x69, 0x64, + 0x41, 0x65, 0x72, 0x0a, 0x4a, 0x67, 0x47, 0x68, 0x46, 0x5a, 0x68, 0x2f, 0x55, 0x73, 0x56, 0x50, + 0x37, 0x41, 0x66, 0x4c, 0x4c, 0x6e, 0x75, 0x4f, 0x57, 0x68, 0x70, 0x35, 0x4d, 0x67, 0x58, 0x70, + 0x6b, 0x38, 0x72, 0x7a, 0x38, 0x50, 0x31, 0x4e, 0x69, 0x50, 0x4a, 0x49, 0x38, 0x6d, 0x57, 0x6c, + 0x6f, 0x55, 0x61, 0x75, 0x34, 0x4d, 0x6c, 0x35, 0x2b, 0x70, 0x71, 0x5a, 0x66, 0x76, 0x39, 0x57, + 0x35, 0x68, 0x76, 0x74, 0x0a, 0x48, 0x4a, 0x79, 0x31, 0x41, 0x59, 0x32, 0x2b, 0x35, 0x58, 0x53, + 0x70, 0x58, 0x7a, 0x2f, 0x36, 0x71, 0x66, 0x61, 0x4a, 0x41, 0x4d, 0x67, 0x2b, 0x38, 0x78, 0x71, + 0x66, 0x32, 0x64, 0x67, 0x55, 0x74, 0x77, 0x5a, 0x72, 0x42, 0x55, 0x2b, 0x5a, 0x52, 0x6e, 0x79, + 0x47, 0x6e, 0x32, 0x33, 0x6a, 0x67, 0x35, 0x67, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, + 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x0a +}; + _UA_END_DECLS #endif /* CERTIFICATES_H_ */ diff --git a/tests/encryption/check_crl_validation.c b/tests/encryption/check_crl_validation.c new file mode 100644 index 00000000000..e3172e9c70b --- /dev/null +++ b/tests/encryption/check_crl_validation.c @@ -0,0 +1,379 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2024 (c) Fraunhofer IOSB (Author: Noel Graf) + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "certificates.h" +#include "check.h" +#include "thread_wrapper.h" + +UA_Server *server; +UA_Boolean running; +THREAD_HANDLE server_thread; + +THREAD_CALLBACK(serverloop) { + while(running) + UA_Server_run_iterate(server, true); + return 0; +} + +static void setup1(void) { + running = true; + + /* Load certificate and private key */ + UA_ByteString certificate; + certificate.length = CERT_DER_LENGTH; + certificate.data = CERT_DER_DATA; + + UA_ByteString privateKey; + privateKey.length = KEY_DER_LENGTH; + privateKey.data = KEY_DER_DATA; + + UA_ByteString rootCa; + rootCa.length = ROOT_CERT_DER_LENGTH; + rootCa.data = ROOT_CERT_DER_DATA; + + UA_ByteString rootCaCrl; + rootCaCrl.length = ROOT_EMPTY_CRL_PEM_LENGTH; + rootCaCrl.data = ROOT_EMPTY_CRL_PEM_DATA; + + UA_ByteString intermediateCa; + intermediateCa.length = INTERMEDIATE_CERT_DER_LENGTH; + intermediateCa.data = INTERMEDIATE_CERT_DER_DATA; + + UA_ByteString intermediateCaCrl; + intermediateCaCrl.length = INTERMEDIATE_EMPTY_CRL_PEM_LENGTH; + intermediateCaCrl.data = INTERMEDIATE_EMPTY_CRL_PEM_DATA; + + /* Load the trustlist */ + size_t trustListSize = 2; + UA_STACKARRAY(UA_ByteString, trustList, trustListSize); + trustList[0] = intermediateCa; + trustList[1] = rootCa; + + /* Load the issuerList */ + size_t issuerListSize = 2; + UA_STACKARRAY(UA_ByteString, issuerList, issuerListSize); + issuerList[0] = intermediateCa; + issuerList[1] = rootCa; + + /* Loading of a revocation list currently unsupported */ + size_t revocationListSize = 2; + UA_STACKARRAY(UA_ByteString, revocationList, revocationListSize); + revocationList[0] = rootCaCrl; + revocationList[1] = intermediateCaCrl; + + server = UA_Server_new(); + ck_assert(server != NULL); + UA_ServerConfig *config = UA_Server_getConfig(server); + UA_ServerConfig_setDefaultWithSecurityPolicies(config, 4840, &certificate, &privateKey, + trustList, trustListSize, + issuerList, issuerListSize, + revocationList, revocationListSize); + + /* Set the ApplicationUri used in the certificate */ + UA_String_clear(&config->applicationDescription.applicationUri); + config->applicationDescription.applicationUri = + UA_STRING_ALLOC("urn:unconfigured:application"); + + UA_Server_run_startup(server); + THREAD_CREATE(server_thread, serverloop); +} + +static void setup2(void) { + running = true; + + /* Load certificate and private key */ + UA_ByteString certificate; + certificate.length = CERT_DER_LENGTH; + certificate.data = CERT_DER_DATA; + + UA_ByteString privateKey; + privateKey.length = KEY_DER_LENGTH; + privateKey.data = KEY_DER_DATA; + + UA_ByteString rootCa; + rootCa.length = ROOT_CERT_DER_LENGTH; + rootCa.data = ROOT_CERT_DER_DATA; + + UA_ByteString rootCaCrl; + rootCaCrl.length = ROOT_EMPTY_CRL_PEM_LENGTH; + rootCaCrl.data = ROOT_EMPTY_CRL_PEM_DATA; + + UA_ByteString intermediateCa; + intermediateCa.length = INTERMEDIATE_CERT_DER_LENGTH; + intermediateCa.data = INTERMEDIATE_CERT_DER_DATA; + + UA_ByteString intermediateCaCrl; + intermediateCaCrl.length = INTERMEDIATE_CRL_PEM_LENGTH; + intermediateCaCrl.data = INTERMEDIATE_CRL_PEM_DATA; + + /* Load the trustlist */ + size_t trustListSize = 2; + UA_STACKARRAY(UA_ByteString, trustList, trustListSize); + trustList[0] = intermediateCa; + trustList[1] = rootCa; + + /* Load the issuerList */ + size_t issuerListSize = 2; + UA_STACKARRAY(UA_ByteString, issuerList, issuerListSize); + issuerList[0] = intermediateCa; + issuerList[1] = rootCa; + + /* Loading of a revocation list currently unsupported */ + size_t revocationListSize = 2; + UA_STACKARRAY(UA_ByteString, revocationList, revocationListSize); + revocationList[0] = rootCaCrl; + revocationList[1] = intermediateCaCrl; + + server = UA_Server_new(); + ck_assert(server != NULL); + UA_ServerConfig *config = UA_Server_getConfig(server); + UA_ServerConfig_setDefaultWithSecurityPolicies(config, 4840, &certificate, &privateKey, + trustList, trustListSize, + issuerList, issuerListSize, + revocationList, revocationListSize); + + /* Set the ApplicationUri used in the certificate */ + UA_String_clear(&config->applicationDescription.applicationUri); + config->applicationDescription.applicationUri = + UA_STRING_ALLOC("urn:unconfigured:application"); + + UA_Server_run_startup(server); + THREAD_CREATE(server_thread, serverloop); +} + +static void setup3(void) { + running = true; + + /* Load certificate and private key */ + UA_ByteString certificate; + certificate.length = CERT_DER_LENGTH; + certificate.data = CERT_DER_DATA; + + UA_ByteString privateKey; + privateKey.length = KEY_DER_LENGTH; + privateKey.data = KEY_DER_DATA; + + UA_ByteString rootCa; + rootCa.length = ROOT_CERT_DER_LENGTH; + rootCa.data = ROOT_CERT_DER_DATA; + + UA_ByteString rootCaCrl; + rootCaCrl.length = ROOT_CRL_PEM_LENGTH; + rootCaCrl.data = ROOT_CRL_PEM_DATA; + + UA_ByteString intermediateCa; + intermediateCa.length = INTERMEDIATE_CERT_DER_LENGTH; + intermediateCa.data = INTERMEDIATE_CERT_DER_DATA; + + UA_ByteString intermediateCaCrl; + intermediateCaCrl.length = INTERMEDIATE_EMPTY_CRL_PEM_LENGTH; + intermediateCaCrl.data = INTERMEDIATE_EMPTY_CRL_PEM_DATA; + + /* Load the trustlist */ + size_t trustListSize = 2; + UA_STACKARRAY(UA_ByteString, trustList, trustListSize); + trustList[0] = intermediateCa; + trustList[1] = rootCa; + + /* Load the issuerList */ + size_t issuerListSize = 2; + UA_STACKARRAY(UA_ByteString, issuerList, issuerListSize); + issuerList[0] = rootCa; + issuerList[1] = intermediateCa; + + /* Loading of a revocation list currently unsupported */ + size_t revocationListSize = 2; + UA_STACKARRAY(UA_ByteString, revocationList, revocationListSize); + revocationList[0] = rootCaCrl; + revocationList[1] = intermediateCaCrl; + + server = UA_Server_new(); + ck_assert(server != NULL); + UA_ServerConfig *config = UA_Server_getConfig(server); + UA_ServerConfig_setDefaultWithSecurityPolicies(config, 4840, &certificate, &privateKey, + trustList, trustListSize, + issuerList, issuerListSize, + revocationList, revocationListSize); + + /* Set the ApplicationUri used in the certificate */ + UA_String_clear(&config->applicationDescription.applicationUri); + config->applicationDescription.applicationUri = + UA_STRING_ALLOC("urn:unconfigured:application"); + + UA_Server_run_startup(server); + THREAD_CREATE(server_thread, serverloop); +} + +static void teardown(void) { + running = false; + THREAD_JOIN(server_thread); + UA_Server_run_shutdown(server); + UA_Server_delete(server); +} + +START_TEST(encryption_connect_valid) { +/* Load certificate and private key */ + UA_ByteString certificate; + certificate.length = APPLICATION_CERT_DER_LENGTH; + certificate.data = APPLICATION_CERT_DER_DATA; + ck_assert_uint_ne(certificate.length, 0); + + UA_ByteString privateKey; + privateKey.length = APPLICATION_KEY_DER_LENGTH; + privateKey.data = APPLICATION_KEY_DER_DATA; + ck_assert_uint_ne(privateKey.length, 0); + + /* Load the trustlist */ + UA_ByteString *trustList = NULL; + size_t trustListSize = 0; + UA_ByteString *revocationList = NULL; + size_t revocationListSize = 0; + + /* Secure client initialization */ + UA_Client *client = UA_Client_new(); + UA_ClientConfig *cc = UA_Client_getConfig(client); + UA_ClientConfig_setDefaultEncryption(cc, certificate, privateKey, + trustList, trustListSize, + revocationList, revocationListSize); + cc->certificateVerification.clear(&cc->certificateVerification); + UA_CertificateVerification_AcceptAll(&cc->certificateVerification); + cc->securityPolicyUri = + UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"); + ck_assert(client != NULL); + + /* Secure client connect */ + UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); + ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); + + UA_Variant val; + UA_Variant_init(&val); + UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE); + retval = UA_Client_readValueAttribute(client, nodeId, &val); + ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); + UA_Variant_clear(&val); + + UA_Client_disconnect(client); + UA_Client_delete(client); +} +END_TEST + +START_TEST(encryption_connect_revoked) { + UA_ByteString certificate; + certificate.length = APPLICATION_CERT_DER_LENGTH; + certificate.data = APPLICATION_CERT_DER_DATA; + ck_assert_uint_ne(certificate.length, 0); + + UA_ByteString privateKey; + privateKey.length = APPLICATION_KEY_DER_LENGTH; + privateKey.data = APPLICATION_KEY_DER_DATA; + ck_assert_uint_ne(privateKey.length, 0); + + /* Load the trustlist */ + UA_ByteString *trustList = NULL; + size_t trustListSize = 0; + UA_ByteString *revocationList = NULL; + size_t revocationListSize = 0; + + /* Secure client initialization */ + UA_Client *client = UA_Client_new(); + UA_ClientConfig *cc = UA_Client_getConfig(client); + UA_ClientConfig_setDefaultEncryption(cc, certificate, privateKey, + trustList, trustListSize, + revocationList, revocationListSize); + cc->certificateVerification.clear(&cc->certificateVerification); + UA_CertificateVerification_AcceptAll(&cc->certificateVerification); + cc->securityPolicyUri = + UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"); + ck_assert(client != NULL); + + /* Secure client connect. The application certificate is revoked by the + * intermediate CA's CRL, so the server rejects the handshake. */ + UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); + ck_assert_uint_eq(retval, UA_STATUSCODE_BADSECURITYCHECKSFAILED); + + UA_Client_disconnect(client); + UA_Client_delete(client); +} +END_TEST + +START_TEST(encryption_connect_issuer_revoked) { + UA_ByteString certificate; + certificate.length = APPLICATION_CERT_DER_LENGTH; + certificate.data = APPLICATION_CERT_DER_DATA; + ck_assert_uint_ne(certificate.length, 0); + + UA_ByteString privateKey; + privateKey.length = APPLICATION_KEY_DER_LENGTH; + privateKey.data = APPLICATION_KEY_DER_DATA; + ck_assert_uint_ne(privateKey.length, 0); + + /* Load the trustlist */ + UA_ByteString *trustList = NULL; + size_t trustListSize = 0; + UA_ByteString *revocationList = NULL; + size_t revocationListSize = 0; + + /* Secure client initialization */ + UA_Client *client = UA_Client_new(); + UA_ClientConfig *cc = UA_Client_getConfig(client); + UA_ClientConfig_setDefaultEncryption(cc, certificate, privateKey, + trustList, trustListSize, + revocationList, revocationListSize); + cc->certificateVerification.clear(&cc->certificateVerification); + UA_CertificateVerification_AcceptAll(&cc->certificateVerification); + cc->securityPolicyUri = + UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"); + ck_assert(client != NULL); + + /* Secure client connect. The intermediate CA certificate is revoked by the + * root CA's CRL, so the issuer of the application certificate is revoked. */ + UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); + ck_assert_uint_eq(retval, UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED); + + UA_Client_disconnect(client); + UA_Client_delete(client); +} +END_TEST + +static Suite* testSuite_encryption(void) { + Suite *s = suite_create("Certificate Revocation List"); + TCase *tc_encryption_valid = tcase_create("Certificate Revocation Valid"); + tcase_add_checked_fixture(tc_encryption_valid, setup1, teardown); + TCase *tc_encryption_revoked = tcase_create("Certificate Revocation Revoked"); + tcase_add_checked_fixture(tc_encryption_revoked, setup2, teardown); + TCase *tc_encryption_revoked2 = tcase_create("Certificate Revocation Revoked2"); + tcase_add_checked_fixture(tc_encryption_revoked2, setup3, teardown); +#ifdef UA_ENABLE_ENCRYPTION + tcase_add_test(tc_encryption_valid, encryption_connect_valid); + tcase_add_test(tc_encryption_revoked, encryption_connect_revoked); + tcase_add_test(tc_encryption_revoked2, encryption_connect_issuer_revoked); +#endif /* UA_ENABLE_ENCRYPTION */ + suite_add_tcase(s,tc_encryption_valid); + suite_add_tcase(s,tc_encryption_revoked); + suite_add_tcase(s,tc_encryption_revoked2); + return s; +} + +int main(void) { + Suite *s = testSuite_encryption(); + SRunner *sr = srunner_create(s); + srunner_set_fork_status(sr, CK_NOFORK); + srunner_run_all(sr,CK_NORMAL); + int number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/encryption/check_encryption_basic128rsa15.c b/tests/encryption/check_encryption_basic128rsa15.c index 9c547fa5411..80bb043163f 100644 --- a/tests/encryption/check_encryption_basic128rsa15.c +++ b/tests/encryption/check_encryption_basic128rsa15.c @@ -75,6 +75,11 @@ static void setup(void) { config->certificateVerification.clear(&config->certificateVerification); UA_CertificateVerification_AcceptAll(&config->certificateVerification); + /* Manually add the Basic128Rsa15 SecurityPolicy. + * It does not get added by default as it is considered unsecure. */ + UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, &certificate, &privateKey); + UA_ServerConfig_addAllEndpoints(config); + /* Set the ApplicationUri used in the certificate */ UA_String_clear(&config->applicationDescription.applicationUri); config->applicationDescription.applicationUri = @@ -118,7 +123,9 @@ START_TEST(encryption_connect) { * security mode as none to see the server's capability * and certificate */ client = UA_Client_new(); - UA_ClientConfig_setDefault(UA_Client_getConfig(client)); + UA_ClientConfig *cc = UA_Client_getConfig(client); + UA_ClientConfig_setDefault(cc); + ck_assert(client != NULL); UA_StatusCode retval = UA_Client_getEndpoints(client, "opc.tcp://localhost:4840", &endpointArraySize, &endpointArray); @@ -147,12 +154,22 @@ START_TEST(encryption_connect) { /* Secure client initialization */ client = UA_Client_new(); - UA_ClientConfig *cc = UA_Client_getConfig(client); + cc = UA_Client_getConfig(client); UA_ClientConfig_setDefaultEncryption(cc, certificate, privateKey, trustList, trustListSize, revocationList, revocationListSize); cc->certificateVerification.clear(&cc->certificateVerification); UA_CertificateVerification_AcceptAll(&cc->certificateVerification); + + /* Manually add the Basic128Rsa15 SecurityPolicy. + * It does not get added by default as it is considered unsecure. */ + cc->securityPolicies = (UA_SecurityPolicy *) + UA_realloc(cc->securityPolicies, sizeof(UA_SecurityPolicy) * + (cc->securityPoliciesSize + 1)); + UA_SecurityPolicy_Basic128Rsa15(&cc->securityPolicies[cc->securityPoliciesSize], + certificate, privateKey, &cc->logger); + cc->securityPoliciesSize++; + cc->securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"); ck_assert(client != NULL); @@ -236,6 +253,16 @@ START_TEST(encryption_connect_pem) { revocationList, revocationListSize); cc->certificateVerification.clear(&cc->certificateVerification); UA_CertificateVerification_AcceptAll(&cc->certificateVerification); + + /* Manually add the Basic128Rsa15 SecurityPolicy. + * It does not get added by default as it is considered unsecure. */ + cc->securityPolicies = (UA_SecurityPolicy *) + UA_realloc(cc->securityPolicies, sizeof(UA_SecurityPolicy) * + (cc->securityPoliciesSize + 1)); + UA_SecurityPolicy_Basic128Rsa15(&cc->securityPolicies[cc->securityPoliciesSize], + certificate, privateKey, &cc->logger); + cc->securityPoliciesSize++; + cc->securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"); ck_assert(client != NULL); diff --git a/tests/encryption/check_encryption_basic256.c b/tests/encryption/check_encryption_basic256.c index 48d14a4978b..57335b2d29e 100644 --- a/tests/encryption/check_encryption_basic256.c +++ b/tests/encryption/check_encryption_basic256.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,11 @@ static void setup(void) { config->certificateVerification.clear(&config->certificateVerification); UA_CertificateVerification_AcceptAll(&config->certificateVerification); + /* Manually add the Basic256 SecurityPolicy. + * It does not get added by default as it is considered unsecure. */ + UA_ServerConfig_addSecurityPolicyBasic256(config, &certificate, &privateKey); + UA_ServerConfig_addAllEndpoints(config); + /* Set the ApplicationUri used in the certificate */ UA_String_clear(&config->applicationDescription.applicationUri); config->applicationDescription.applicationUri = @@ -156,6 +162,16 @@ START_TEST(encryption_connect) { revocationList, revocationListSize); cc->certificateVerification.clear(&cc->certificateVerification); UA_CertificateVerification_AcceptAll(&cc->certificateVerification); + + /* Manually add the Basic256 SecurityPolicy. + * It does not get added by default as it is considered unsecure. */ + cc->securityPolicies = (UA_SecurityPolicy *) + UA_realloc(cc->securityPolicies, sizeof(UA_SecurityPolicy) * + (cc->securityPoliciesSize + 1)); + UA_SecurityPolicy_Basic256(&cc->securityPolicies[cc->securityPoliciesSize], + certificate, privateKey, &cc->logger); + cc->securityPoliciesSize++; + cc->securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic256"); ck_assert(client != NULL); @@ -239,6 +255,16 @@ START_TEST(encryption_connect_pem) { revocationList, revocationListSize); cc->certificateVerification.clear(&cc->certificateVerification); UA_CertificateVerification_AcceptAll(&cc->certificateVerification); + + /* Manually add the Basic256 SecurityPolicy. + * It does not get added by default as it is considered unsecure. */ + cc->securityPolicies = (UA_SecurityPolicy *) + UA_realloc(cc->securityPolicies, sizeof(UA_SecurityPolicy) * + (cc->securityPoliciesSize + 1)); + UA_SecurityPolicy_Basic256(&cc->securityPolicies[cc->securityPoliciesSize], + certificate, privateKey, &cc->logger); + cc->securityPoliciesSize++; + cc->securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic256"); ck_assert(client != NULL); diff --git a/tests/pubsub/check_pubsub_connection_mqtt.c b/tests/pubsub/check_pubsub_connection_mqtt.c index 834caa5c219..a836a8d3515 100644 --- a/tests/pubsub/check_pubsub_connection_mqtt.c +++ b/tests/pubsub/check_pubsub_connection_mqtt.c @@ -15,13 +15,17 @@ #include "ua_server_internal.h" #include - -//#define TEST_MQTT_SERVER "opc.mqtt://test.mosquitto.org:1883" -#define TEST_MQTT_SERVER "opc.mqtt://localhost:1883" +#include UA_Server *server = NULL; UA_ServerConfig *config = NULL; +static char* get_mqtt_broker_address(void) { + char* broker = getenv("OPEN62541_TEST_MQTT_BROKER"); + if (!broker) broker = "opc.mqtt://localhost:1883"; + return broker; +} + static void setup(void) { server = UA_Server_new(); config = UA_Server_getConfig(server); @@ -39,7 +43,7 @@ START_TEST(AddConnectionsWithMinimalValidConfiguration){ memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); connectionConfig.name = UA_STRING("Mqtt Connection"); UA_NetworkAddressUrlDataType networkAddressUrl = - {UA_STRING_NULL, UA_STRING(TEST_MQTT_SERVER)}; + {UA_STRING_NULL, UA_STRING(get_mqtt_broker_address())}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); connectionConfig.transportProfileUri = @@ -60,7 +64,7 @@ START_TEST(AddRemoveAddConnectionWithMinimalValidConfiguration){ memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); connectionConfig.name = UA_STRING("Mqtt Connection"); UA_NetworkAddressUrlDataType networkAddressUrl = - {UA_STRING_NULL, UA_STRING(TEST_MQTT_SERVER)}; + {UA_STRING_NULL, UA_STRING(get_mqtt_broker_address())}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); connectionConfig.transportProfileUri = @@ -86,7 +90,7 @@ START_TEST(AddConnectionWithInvalidAddress){ memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); connectionConfig.name = UA_STRING("MQTT Connection"); UA_NetworkAddressUrlDataType networkAddressUrl = - {UA_STRING_NULL, UA_STRING("opc.mqtt://127.0..1:1883/")}; + {UA_STRING_NULL, UA_STRING(get_mqtt_broker_address())}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); connectionConfig.transportProfileUri = @@ -104,7 +108,7 @@ START_TEST(AddConnectionWithUnknownTransportURL){ memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); connectionConfig.name = UA_STRING("MQTT Connection"); UA_NetworkAddressUrlDataType networkAddressUrl = - {UA_STRING_NULL, UA_STRING(TEST_MQTT_SERVER)}; + {UA_STRING_NULL, UA_STRING(get_mqtt_broker_address())}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); connectionConfig.transportProfileUri = @@ -124,7 +128,7 @@ START_TEST(AddConnectionWithNullConfig){ START_TEST(AddSingleConnectionWithMaximalConfiguration){ UA_NetworkAddressUrlDataType networkAddressUrlData = - {UA_STRING("127.0.0.1"), UA_STRING(TEST_MQTT_SERVER)}; + {UA_STRING("127.0.0.1"), UA_STRING(get_mqtt_broker_address())}; UA_Variant address; UA_Variant_setScalar(&address, &networkAddressUrlData, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); UA_KeyValuePair connectionOptions[3]; @@ -156,7 +160,7 @@ START_TEST(AddSingleConnectionWithMaximalConfiguration){ START_TEST(GetMaximalConnectionConfigurationAndCompareValues){ UA_NetworkAddressUrlDataType networkAddressUrlData = - {UA_STRING("127.0.0.1"), UA_STRING(TEST_MQTT_SERVER)}; + {UA_STRING("127.0.0.1"), UA_STRING(get_mqtt_broker_address())}; UA_Variant address; UA_Variant_setScalar(&address, &networkAddressUrlData, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); UA_KeyValuePair connectionOptions[3]; diff --git a/tests/server/check_accesscontrol.c b/tests/server/check_accesscontrol.c index 9706e8af2a4..1c5f2ddc4f4 100644 --- a/tests/server/check_accesscontrol.c +++ b/tests/server/check_accesscontrol.c @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -85,6 +86,64 @@ START_TEST(Client_pass_fail) { UA_Client_delete(client); } END_TEST +static UA_Boolean +allowBrowseNode(UA_Server *s, UA_AccessControl *ac, + const UA_NodeId *sessionId, void *sessionContext, + const UA_NodeId *nodeId, void *nodeContext) { + UA_Variant attribute; + UA_Variant_init(&attribute); + UA_Server_getSessionParameter(s, sessionId, "my_custom_attribute", &attribute); + return true; +} + +static void setCustomAccessControl(UA_ServerConfig* config) { + UA_Boolean allowAnonymous = true; + UA_AccessControl_default(config, allowAnonymous, NULL, NULL, 0, NULL); + config->accessControl.allowBrowseNode = allowBrowseNode; +} + +START_TEST(Server_sessionParameter) { + server = UA_Server_new(); + UA_ServerConfig *config = UA_Server_getConfig(server); + UA_ServerConfig_setDefault(config); + setCustomAccessControl(config); + UA_Server_run_startup(server); + + running = true; + THREAD_CREATE(server_thread, serverloop); + + UA_Client *client = UA_Client_new(); + UA_ClientConfig_setDefault(UA_Client_getConfig(client)); + UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); + + ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); + + UA_BrowseDescription bd; + UA_BrowseDescription_init(&bd); + bd.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER); + bd.browseDirection = UA_BROWSEDIRECTION_BOTH; + bd.includeSubtypes = true; + bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES); + + UA_BrowseRequest request; + UA_BrowseRequest_init(&request); + request.nodesToBrowse = &bd; + request.nodesToBrowseSize = 1; + + UA_BrowseResponse br = UA_Client_Service_browse(client, request); + UA_assert(br.resultsSize == 1); + UA_assert(br.results[0].referencesSize > 0); + UA_assert(br.results[0].statusCode == UA_STATUSCODE_GOOD); + UA_BrowseResponse_clear(&br); + + UA_Client_disconnect(client); + UA_Client_delete(client); + + running = false; + THREAD_JOIN(server_thread); + UA_Server_run_shutdown(server); + UA_Server_delete(server); +} END_TEST static Suite* testSuite_Client(void) { Suite *s = suite_create("Client"); @@ -95,6 +154,10 @@ static Suite* testSuite_Client(void) { tcase_add_test(tc_client_user, Client_user_fail); tcase_add_test(tc_client_user, Client_pass_fail); suite_add_tcase(s,tc_client_user); + + TCase *tc_server = tcase_create("Server-Side Access Control"); + tcase_add_test(tc_server, Server_sessionParameter); + suite_add_tcase(s,tc_server); return s; } diff --git a/tests/server/check_monitoreditem_filter.c b/tests/server/check_monitoreditem_filter.c index 3176a74c13a..f43babe5335 100644 --- a/tests/server/check_monitoreditem_filter.c +++ b/tests/server/check_monitoreditem_filter.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "client/ua_client_internal.h" @@ -915,6 +916,84 @@ START_TEST(Server_MonitoredItemsAbsoluteFilterSetOnCreate) { } END_TEST +static UA_StatusCode +setEmptyArray(UA_Client *thisClient, UA_NodeId node) { + UA_Variant variant; + UA_Variant_init (&variant); + UA_Variant_setArray(&variant, NULL, 0, &UA_TYPES[UA_TYPES_DOUBLE]); + return UA_Client_writeValueAttribute(thisClient, node, &variant); +} + +START_TEST(Server_MonitoredItemsAbsoluteFilterNULLValue) { + UA_DataValue_init(&lastValue); + /* define a monitored item with an absolute filter with deadbandvalue = 2.0 */ + UA_MonitoredItemCreateRequest item = UA_MonitoredItemCreateRequest_default(outNodeId); + UA_DataChangeFilter filter; + UA_DataChangeFilter_init(&filter); + filter.trigger = UA_DATACHANGETRIGGER_STATUSVALUE; + filter.deadbandType = UA_DEADBANDTYPE_ABSOLUTE; + filter.deadbandValue = 2.0; + item.requestedParameters.filter.encoding = UA_EXTENSIONOBJECT_DECODED; + item.requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_DATACHANGEFILTER]; + item.requestedParameters.filter.content.decoded.data = &filter; + UA_UInt32 newMonitoredItemIds[1]; + UA_Client_DataChangeNotificationCallback callbacks[1]; + callbacks[0] = dataChangeHandler; + UA_Client_DeleteMonitoredItemCallback deleteCallbacks[1] = {NULL}; + void *contexts[1]; + contexts[0] = NULL; + + /* Set empty array value so that the initial value data ptr for the monitored item is NULL */ + ck_assert_uint_eq(setEmptyArray(client, outNodeId), UA_STATUSCODE_GOOD); + + UA_CreateMonitoredItemsRequest createRequest; + UA_CreateMonitoredItemsRequest_init(&createRequest); + createRequest.subscriptionId = subId; + createRequest.timestampsToReturn = UA_TIMESTAMPSTORETURN_BOTH; + createRequest.itemsToCreate = &item; + createRequest.itemsToCreateSize = 1; + UA_CreateMonitoredItemsResponse createResponse = + UA_Client_MonitoredItems_createDataChanges(client, createRequest, contexts, + callbacks, deleteCallbacks); + + ck_assert_uint_eq(createResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); + ck_assert_uint_eq(createResponse.resultsSize, 1); + ck_assert_uint_eq(createResponse.results[0].statusCode, UA_STATUSCODE_GOOD); + newMonitoredItemIds[0] = createResponse.results[0].monitoredItemId; + UA_CreateMonitoredItemsResponse_clear(&createResponse); + + // Do we get initial value ? + notificationReceived = false; + countNotificationReceived = 0; + ck_assert_uint_eq(waitForNotification(1, 10), UA_STATUSCODE_GOOD); + ck_assert_uint_eq(notificationReceived, true); + ck_assert_uint_eq(countNotificationReceived, 1); + ck_assert(lastValue.value.data == NULL); + + notificationReceived = false; + ck_assert_uint_eq(setDouble(client, outNodeId, 42.0), UA_STATUSCODE_GOOD); + ck_assert_uint_eq(waitForNotification(1, 10), UA_STATUSCODE_GOOD); + ck_assert_uint_eq(notificationReceived, true); + ck_assert_uint_eq(countNotificationReceived, 2); + + // remove monitored item + UA_DeleteMonitoredItemsRequest deleteRequest; + UA_DeleteMonitoredItemsRequest_init(&deleteRequest); + deleteRequest.subscriptionId = subId; + deleteRequest.monitoredItemIds = newMonitoredItemIds; + deleteRequest.monitoredItemIdsSize = 1; + + UA_DeleteMonitoredItemsResponse deleteResponse = + UA_Client_MonitoredItems_delete(client, deleteRequest); + + ck_assert_uint_eq(deleteResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); + ck_assert_uint_eq(deleteResponse.resultsSize, 1); + ck_assert_uint_eq(deleteResponse.results[0], UA_STATUSCODE_GOOD); + + UA_DeleteMonitoredItemsResponse_clear(&deleteResponse); +} +END_TEST + START_TEST(Server_MonitoredItemsPercentFilterSetOnCreateMissingEURange) { UA_DataValue_init(&lastValue); /* define a monitored item with an percent filter with deadbandvalue = 2.0 */ @@ -1130,11 +1209,16 @@ static Suite* testSuite_Client(void) { tcase_add_test(tc_server, Server_MonitoredItemsAbsoluteFilterSetOnCreateRemoveLater); tcase_add_test(tc_server, Server_MonitoredItemsPercentFilterSetOnCreateMissingEURange); tcase_add_test(tc_server, Server_MonitoredItemsPercentFilterSetLaterMissingEURange); + + + tcase_add_test(tc_server, Server_MonitoredItemsAbsoluteFilterNULLValue); + #ifdef UA_ENABLE_DA tcase_add_test(tc_server, Server_MonitoredItemsPercentFilterSetOnCreate); tcase_add_test(tc_server, Server_MonitoredItemsPercentFilterSetOnCreateDeadBandValueOutOfRange); #endif /* UA_ENABLE_DA */ #endif /* UA_ENABLE_SUBSCRIPTIONS */ + suite_add_tcase(s, tc_server); return s; diff --git a/tools/azure-devops/debian/install.sh b/tools/azure-devops/debian/install.sh index 19935fa6299..6168486c9a5 100644 --- a/tools/azure-devops/debian/install.sh +++ b/tools/azure-devops/debian/install.sh @@ -12,17 +12,17 @@ sudo apt install -y \ graphviz \ latexmk \ libsubunit-dev \ - python-sphinx \ + python3-sphinx \ python3-pip \ tar \ texlive-fonts-recommended \ - texlive-generic-extra \ + texlive-extra-utils \ texlive-latex-extra \ wget -wget https://github.com/ARMmbed/mbedtls/archive/mbedtls-2.7.1.tar.gz -tar xf mbedtls-2.7.1.tar.gz -cd mbedtls-mbedtls-2.7.1 +wget https://github.com/ARMmbed/mbedtls/archive/mbedtls-2.28.2.tar.gz +tar xf mbedtls-2.28.2.tar.gz +cd mbedtls-mbedtls-2.28.2 cmake -DENABLE_TESTING=Off . make -j sudo make install diff --git a/tools/azure-devops/win/build.ps1 b/tools/azure-devops/win/build.ps1 index 8986d409101..b443eee5930 100644 --- a/tools/azure-devops/win/build.ps1 +++ b/tools/azure-devops/win/build.ps1 @@ -26,18 +26,15 @@ try { if ($env:CC_SHORTNAME -eq "mingw") { - } elseif ($env:CC_SHORTNAME -eq "clang-mingw") { - # Setup clang - $env:CC = "clang --target=x86_64-w64-mingw32" - $env:CXX = "clang++ --target=x86_64-w64-mingw32" - clang --version - } else { - $vcpkg_toolchain = '-DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake"' - $vcpkg_triplet = '-DVCPKG_TARGET_TRIPLET="x86-windows-static"' - # since https://github.com/Microsoft/vcpkg/commit/0334365f516c5f229ff4fcf038c7d0190979a38a#diff-464a170117fa96bf98b2f8d224bf503c - # vcpkg need to have "C:\Tools\vcpkg\installed\x86-windows-static" - New-Item -Force -ItemType directory -Path "C:/vcpkg/installed/x86-windows-static" - } +} elseif ($env:CC_SHORTNAME -eq "clang-mingw") { + # Setup clang + $env:CC = "clang --target=x86_64-w64-mingw32" + $env:CXX = "clang++ --target=x86_64-w64-mingw32" + clang --version +} else { + $vcpkg_toolchain = '-DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake"' + $vcpkg_triplet = '-DVCPKG_TARGET_TRIPLET="x64-windows-static"' +} $cmake_cnf="$vcpkg_toolchain", "$vcpkg_triplet", "-G`"$env:GENERATOR`"", "-DUA_FORCE_CPP:BOOL=$env:FORCE_CXX" @@ -47,8 +44,8 @@ try { Copy-Item AUTHORS pack Copy-Item README.md pack - # Only execute unit tests on vs2017 to save compilation time - if ($env:CC_SHORTNAME -eq "vs2017") { + # Only execute unit tests on vs2019 to save compilation time + if ($env:CC_SHORTNAME -eq "vs2019") { Write-Host -ForegroundColor Green "`n###################################################################" Write-Host -ForegroundColor Green "`n##### Testing $env:CC_NAME with unit tests #####`n" New-Item -ItemType directory -Path "build" @@ -66,8 +63,7 @@ try { -DUA_ENABLE_PUBSUB:BOOL=ON ` -DUA_ENABLE_PUBSUB_DELTAFRAMES:BOOL=ON ` -DUA_ENABLE_PUBSUB_INFORMATIONMODEL:BOOL=ON ` - -DUA_ENABLE_PUBSUB_MONITORING:BOOL=ON ` - -DUA_ENABLE_UNIT_TESTS_MEMCHECK=ON .. + -DUA_ENABLE_PUBSUB_MONITORING:BOOL=ON .. & cmake --build . --config Debug if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { Write-Host -ForegroundColor Red "`n`n*** Make failed. Exiting ... ***" diff --git a/tools/azure-devops/win/install.ps1 b/tools/azure-devops/win/install.ps1 index 7e029ca61dd..93a9791ef8c 100644 --- a/tools/azure-devops/win/install.ps1 +++ b/tools/azure-devops/win/install.ps1 @@ -21,36 +21,32 @@ try { # Otherwise we run into issue: https://github.com/msys2/MINGW-packages/issues/6576 & C:\msys64\usr\bin\pacman -Syu - Write-Host -ForegroundColor Green "`n### Installing mbedtls via PacMan ###`n" - & C:\msys64\usr\bin\pacman --noconfirm --needed -S mingw-w64-x86_64-mbedtls - if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { - Write-Host -ForegroundColor Red "`n`n*** Install failed. Exiting ... ***" - exit $LASTEXITCODE - } - - } elseif ($env:CC_SHORTNAME -eq "vs2015" -or $env:CC_SHORTNAME -eq "vs2017") { - Write-Host -ForegroundColor Green "`n### Installing mbedtls via vcpkg ###`n" - & vcpkg install mbedtls:x86-windows-static - if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { - Write-Host -ForegroundColor Red "`n`n*** Install failed. Exiting ... ***" - exit $LASTEXITCODE - } + Write-Host -ForegroundColor Green "`n### Installing mbedtls via PacMan ###`n" + & C:\msys64\usr\bin\pacman --noconfirm --needed -S mingw-w64-x86_64-mbedtls + if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { + Write-Host -ForegroundColor Red "`n`n*** Install of mbedTLS failed. Exiting ... ***" + exit $LASTEXITCODE + } - Write-Host -ForegroundColor Green "`n### Installing libcheck via vcpkg ###`n" - & vcpkg install check:x86-windows-static - if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { - Write-Host -ForegroundColor Red "`n`n*** Install failed. Exiting ... ***" - exit $LASTEXITCODE - } + & C:\msys64\usr\bin\pacman --noconfirm --needed -S mingw-w64-x86_64-check + if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { + Write-Host -ForegroundColor Red "`n`n*** Install of check failed. Exiting ... ***" + exit $LASTEXITCODE + } +} else { + Write-Host -ForegroundColor Green "`n### Installing mbedtls via vcpkg ###`n" + & vcpkg install mbedtls:x64-windows-static + if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { + Write-Host -ForegroundColor Red "`n`n*** Install failed. Exiting ... ***" + exit $LASTEXITCODE + } - Write-Host -ForegroundColor Green "`n### Installing DrMemory ###`n" - & choco install -y --no-progress drmemory.portable - if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { - Write-Host -ForegroundColor Red "`n`n*** Install failed. Exiting ... ***" - exit $LASTEXITCODE - } - #$env:Path = 'C:\Program Files (x86)\Dr. Memory\bin;' + $env:Path - #[System.Environment]::SetEnvironmentVariable('Path', $path, 'Machine') + Write-Host -ForegroundColor Green "`n### Installing libcheck via vcpkg ###`n" + & vcpkg install check:x64-windows-static + if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { + Write-Host -ForegroundColor Red "`n`n*** Install failed. Exiting ... ***" + exit $LASTEXITCODE + } } if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { diff --git a/tools/cmake/FindCheck.cmake b/tools/cmake/FindCheck.cmake index ed410c16b83..b02dc148369 100644 --- a/tools/cmake/FindCheck.cmake +++ b/tools/cmake/FindCheck.cmake @@ -22,6 +22,23 @@ INCLUDE( FindPkgConfig ) # Take care about check.pc settings PKG_SEARCH_MODULE( CHECK check ) +# pkg-config exports the plural CHECK_INCLUDE_DIRS and linker flags with the +# architecture-specific library directory. Mirror them to the singular +# CHECK_INCLUDE_DIR and CHECK_LIBRARIES that this module documents and the build +# expects. Do not resolve the library again with find_library(), because that can +# pick a host-architecture library during multilib/cross builds. +IF( CHECK_FOUND ) + IF( NOT CHECK_INCLUDE_DIR ) + SET( CHECK_INCLUDE_DIR ${CHECK_INCLUDE_DIRS} ) + ENDIF() + IF( CHECK_LDFLAGS ) + SET( CHECK_LIBRARIES ${CHECK_LDFLAGS} ) + IF( CHECK_LDFLAGS_OTHER ) + LIST( APPEND CHECK_LIBRARIES ${CHECK_LDFLAGS_OTHER} ) + ENDIF() + ENDIF() +ENDIF() + # Look for CHECK include dir and libraries IF( NOT CHECK_FOUND ) IF ( CHECK_INSTALL_DIR )