From a955d8dd929861cbfb98a4ee35186298ab1fb515 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Wed, 18 Feb 2026 09:23:09 +0200 Subject: [PATCH] Fix macOS build and other build fixes Fixes #715, #716, #717 Signed-off-by: Raul Metsma --- CMakeLists.txt | 18 ++--- etc/Doxyfile.in | 16 ++-- examples/CMakeLists.txt | 1 - prepare_osx_build_environment.sh | 2 +- src/CMakeLists.txt | 59 +++++++++------ src/XMLDocument.h | 1 + test/CMakeLists.txt | 8 +- xmlsec1-1.3.5.legacy.patch | 126 +++++++++++++++++++++++++++++++ 8 files changed, 183 insertions(+), 48 deletions(-) create mode 100644 xmlsec1-1.3.5.legacy.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index cd230451d..393e45ac9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ project(libdigidocpp VERSION 4.4.0 DESCRIPTION "C++ library for digital signatures and validation of digitally signed documents" HOMEPAGE_URL https://github.com/open-eid/libdigidocpp ) -set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) list(APPEND CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}) macro(SET_ENV NAME DEF) @@ -24,12 +24,12 @@ include(GNUInstallDirs) set_env( TSL_URL "https://ec.europa.eu/tools/lotl/eu-lotl.xml" CACHE STRING "TSL trust list primary URL" ) set_env( TSL_CERTS - ${CMAKE_SOURCE_DIR}/etc/tl-mp1.crt - ${CMAKE_SOURCE_DIR}/etc/tl-mp2.crt - ${CMAKE_SOURCE_DIR}/etc/tl-mp3.crt - ${CMAKE_SOURCE_DIR}/etc/tl-mp4.crt - ${CMAKE_SOURCE_DIR}/etc/tl-mp5.crt - ${CMAKE_SOURCE_DIR}/etc/tl-mp6.crt + ${PROJECT_SOURCE_DIR}/etc/tl-mp1.crt + ${PROJECT_SOURCE_DIR}/etc/tl-mp2.crt + ${PROJECT_SOURCE_DIR}/etc/tl-mp3.crt + ${PROJECT_SOURCE_DIR}/etc/tl-mp4.crt + ${PROJECT_SOURCE_DIR}/etc/tl-mp5.crt + ${PROJECT_SOURCE_DIR}/etc/tl-mp6.crt CACHE FILEPATH "TSL trust list signing certificates" ) set_env(TSA_URL "https://eid-dd.ria.ee/ts" CACHE STRING "Default TSA URL") set_env( SIVA_URL "https://siva.eesti.ee/V3/validate" CACHE STRING "Default SiVa validation service URL" ) @@ -92,13 +92,13 @@ endif() find_package(Doxygen) if(TARGET Doxygen::doxygen) - configure_file( ${CMAKE_SOURCE_DIR}/etc/Doxyfile.in Doxyfile @ONLY ) + configure_file(${PROJECT_SOURCE_DIR}/etc/Doxyfile.in Doxyfile @ONLY) add_custom_target( docs ALL Doxygen::doxygen Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM ) - install( DIRECTORY ${CMAKE_BINARY_DIR}/doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR} ) + install(DIRECTORY ${PROJECT_BINARY_DIR}/doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR}) install( DIRECTORY doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR} ) endif() diff --git a/etc/Doxyfile.in b/etc/Doxyfile.in index 3737d8041..73c5a949d 100644 --- a/etc/Doxyfile.in +++ b/etc/Doxyfile.in @@ -61,7 +61,7 @@ PROJECT_BRIEF = # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = @CMAKE_SOURCE_DIR@/ID.ico +PROJECT_LOGO = @PROJECT_SOURCE_DIR@/ID.ico # With the PROJECT_ICON tag one can specify an icon that is included in the tabs # when the HTML document is shown. Doxygen will copy the logo to the output @@ -74,7 +74,7 @@ PROJECT_ICON = # entered, it will be relative to the location where Doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = @CMAKE_BINARY_DIR@/doc/ +OUTPUT_DIRECTORY = @PROJECT_BINARY_DIR@/doc/ # If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format @@ -965,8 +965,8 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @CMAKE_SOURCE_DIR@/src \ - @CMAKE_SOURCE_DIR@/libdigidocpp.dox +INPUT = @PROJECT_SOURCE_DIR@/src \ + @PROJECT_SOURCE_DIR@/libdigidocpp.dox # This tag can be used to specify the character encoding of the source files # that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses @@ -1076,8 +1076,8 @@ EXCLUDE_SYMBOLS = digidoc::*Private \ # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/ \ - @CMAKE_BINARY_DIR@/ +EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/ \ + @PROJECT_BINARY_DIR@/ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and @@ -1097,7 +1097,7 @@ EXAMPLE_RECURSIVE = NO # that contain images that are to be included in the documentation (see the # \image command). -IMAGE_PATH = @CMAKE_SOURCE_DIR@/doc/images/ +IMAGE_PATH = @PROJECT_SOURCE_DIR@/doc/images/ # The INPUT_FILTER tag can be used to specify a program that Doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1358,7 +1358,7 @@ HTML_STYLESHEET = # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = @CMAKE_SOURCE_DIR@/etc/Doxyfile.css +HTML_EXTRA_STYLESHEET = @PROJECT_SOURCE_DIR@/etc/Doxyfile.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d24c896be..353cb30c2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,3 @@ -include_directories( ${CMAKE_SOURCE_DIR}/src ) add_executable( pkcs11sign pkcs11sign.cpp ) set_target_properties( pkcs11sign PROPERTIES LINK_LIBRARIES digidocpp diff --git a/prepare_osx_build_environment.sh b/prepare_osx_build_environment.sh index 6a49719e8..13acc2153 100755 --- a/prepare_osx_build_environment.sh +++ b/prepare_osx_build_environment.sh @@ -57,7 +57,7 @@ function xmlsec { rm -rf ${XMLSEC_DIR} tar xf ${XMLSEC_DIR}.tar.gz cd ${XMLSEC_DIR} - patch -Np1 -i ../vcpkg-ports/xmlsec/xmlsec1-1.3.5.legacy.patch + patch -Np1 -i ../xmlsec1-1.3.5.legacy.patch case "${ARGS}" in *iphone*) CONFIGURE="--host=aarch64-apple-darwin --enable-static --disable-shared --without-libxslt" ;; *) CONFIGURE="--disable-static --enable-shared" ;; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f50cc721b..31137bfda 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ set_env(BUILD_NUMBER 0) set(VERSION ${PROJECT_VERSION}.${BUILD_NUMBER}) configure_file( libdigidocpp.pc.cmake libdigidocpp.pc @ONLY ) -configure_file( ${CMAKE_SOURCE_DIR}/etc/digidocpp.conf.cmake digidocpp.conf ) +configure_file(${PROJECT_SOURCE_DIR}/etc/digidocpp.conf.cmake digidocpp.conf) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/tslcerts.h "namespace digidoc {\nstatic const std::vector tslcerts {\n") foreach(TSL_CERT ${TSL_CERTS}) @@ -23,7 +23,7 @@ foreach(TSL_CERT ${TSL_CERTS}) endforeach() file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/tslcerts.h "};\n}") -set(SCHEMA_DIR ${CMAKE_SOURCE_DIR}/etc/schema) +set(SCHEMA_DIR ${PROJECT_SOURCE_DIR}/etc/schema) set( SCHEMA_FILES ${SCHEMA_DIR}/conf.xsd ${SCHEMA_DIR}/OpenDocument_manifest_v1_2.xsd @@ -66,7 +66,10 @@ add_library(digidocpp_util STATIC util/log.cpp ) -target_link_libraries(digidocpp_util PUBLIC digidocpp_ver PRIVATE $<$,$>:-framework\ CoreFoundation>) +target_link_libraries(digidocpp_util + PUBLIC $ + PRIVATE $<$,$>:-framework\ CoreFoundation> +) add_library(digidocpp_tsl STATIC crypto/Connect.cpp @@ -82,7 +85,7 @@ set_target_properties(digidocpp_util digidocpp_tsl PROPERTIES POSITION_INDEPENDENT_CODE YES ) -target_include_directories(digidocpp_tsl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(digidocpp_tsl PUBLIC $) target_link_libraries(digidocpp_tsl digidocpp_util @@ -252,7 +255,11 @@ if(SWIG_FOUND) endif() endif() -install( TARGETS digidocpp +if(NOT ${BUILD_SHARED_LIBS}) + set(STATIC_TARGETS minizip digidocpp_tsl digidocpp_util) +endif() + +install(TARGETS digidocpp ${STATIC_TARGETS} EXPORT libdigidocppExport LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -261,29 +268,31 @@ install( TARGETS digidocpp PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/digidocpp FRAMEWORK DESTINATION ${FRAMEWORK_DESTINATION} ) -if(NOT ANDROID) - install(EXPORT libdigidocppExport - FILE libdigidocpp-config.cmake - NAMESPACE digidocpp:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdigidocpp - ) - include(CMakePackageConfigHelpers) - write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/libdigidocpp-config-version.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion - ) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libdigidocpp-config-version.cmake" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdigidocpp - ) -endif() + +install(EXPORT libdigidocppExport + FILE libdigidocpp-config.cmake + NAMESPACE digidocpp:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdigidocpp +) +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/libdigidocpp-config-version.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libdigidocpp-config-version.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libdigidocpp +) if(WIN32) list(APPEND CRYPTO_HEADER crypto/WinSigner.h) target_compile_options(digidocpp_util PUBLIC "/guard:cf") target_link_options(digidocpp PUBLIC "/guard:cf") target_link_libraries(digidocpp PRIVATE Crypt32 cryptui ncrypt) - install(FILES $ $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) + install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) + if(TARGET digidoc-tool) + install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) + endif() if(SIGNCERT) foreach(TARGET digidocpp digidoc-tool digidoc_java digidoc_csharp digidoc_python) if (TARGET ${TARGET}) @@ -310,7 +319,7 @@ if( FRAMEWORK ) set_source_files_properties( ${CRYPTO_HEADER} PROPERTIES MACOSX_PACKAGE_LOCATION Headers/crypto ) list(GET OPENSSL_LIBRARIES 0 LIBPATH) get_filename_component( LIBPATH ${LIBPATH} PATH ) - set(COPY_LIBRARIES_SCRIPT ${CMAKE_BINARY_DIR}/copy_libraries.cmake) + set(COPY_LIBRARIES_SCRIPT ${PROJECT_BINARY_DIR}/copy_libraries.cmake) file(WRITE ${COPY_LIBRARIES_SCRIPT} " message(\"Copy dependencies: \$ENV{LIBRARY} \$ENV{BUNDLE_DIR}\") file(GET_RUNTIME_DEPENDENCIES LIBRARIES \$ENV{LIBRARY} RESOLVED_DEPENDENCIES_VAR OUT) @@ -372,13 +381,13 @@ if( FRAMEWORK ) add_custom_target(pkgbuild DEPENDS digidocpp $ COMMAND DESTDIR=install ${CMAKE_COMMAND} --install . COMMAND pkgbuild --root install "$<$:--sign;${SIGNCERT}>" - ${CMAKE_BINARY_DIR}/libdigidocpp_${VERSION}$ENV{VER_SUFFIX}.pkg + ${PROJECT_BINARY_DIR}/libdigidocpp_${VERSION}$ENV{VER_SUFFIX}.pkg COMMAND_EXPAND_LISTS ) add_custom_target(zipdebug DEPENDS digidocpp $ COMMAND dsymutil -o libdigidocpp.dSYM $ $<$:$> - COMMAND zip -r ${CMAKE_BINARY_DIR}/libdigidocpp-dbg_${VERSION}$ENV{VER_SUFFIX}.zip libdigidocpp.dSYM + COMMAND zip -r ${PROJECT_BINARY_DIR}/libdigidocpp-dbg_${VERSION}$ENV{VER_SUFFIX}.zip libdigidocpp.dSYM ) else() if(NOT ${BUILD_SHARED_LIBS}) diff --git a/src/XMLDocument.h b/src/XMLDocument.h index c81cf03e4..36e8c280c 100644 --- a/src/XMLDocument.h +++ b/src/XMLDocument.h @@ -342,6 +342,7 @@ struct XMLDocument: public unique_free_d, public XMLNode auto result = xmlParseDocument(ctxt.get()); if(result != 0 || !ctxt->wellFormed) { + xmlFreeDoc(ctxt->myDoc); if(const xmlError *lastError = xmlCtxtGetLastError(ctxt.get())) THROW("%s", lastError->message); THROW("Failed to parse XML document from stream"); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 49c7b5b97..04164530e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,7 @@ set_env(TEST_FORMAT XML CACHE STRING "Test result format (XML/JUNIT)") set( CMAKE_SKIP_RPATH OFF ) add_definitions( - -DDIGIDOCPPCONF="${CMAKE_SOURCE_DIR}/etc/schema" + -DDIGIDOCPPCONF="${PROJECT_SOURCE_DIR}/etc/schema" -DPKCS11_MODULE="${PKCS11_MODULE}" -DSIVA_URL="${SIVA_URL}" ) @@ -15,7 +15,7 @@ if(WIN32) endif() add_test(NAME runtest COMMAND ${CMAKE_CURRENT_BINARY_DIR}/unittests --build_info=YES --report_level=no --logger=${TEST_FORMAT},all,${CMAKE_CURRENT_BINARY_DIR}/libdigidocpp.xml -- ${CMAKE_CURRENT_SOURCE_DIR}/data - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src ) # Bad status tests @@ -26,7 +26,7 @@ foreach(TEST CA-non-qa no_QCStatement no_QCSD ) add_test(NAME TSLTest_${TEST} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/TSLTests -- EE_T-${TEST}.xml bad ${CMAKE_CURRENT_SOURCE_DIR}/data - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src ) endforeach() @@ -37,7 +37,7 @@ foreach(TEST CA-withdrawn-granted-before CA-noqscd-granted-before ) add_test(NAME TSLTest_${TEST} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/TSLTests -- EE_T-${TEST}.xml good ${CMAKE_CURRENT_SOURCE_DIR}/data - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src ) endforeach() diff --git a/xmlsec1-1.3.5.legacy.patch b/xmlsec1-1.3.5.legacy.patch new file mode 100644 index 000000000..afcc0dee7 --- /dev/null +++ b/xmlsec1-1.3.5.legacy.patch @@ -0,0 +1,126 @@ +--- xmlsec1-1.3.7.orig/src/openssl/signatures.c 2025-02-11 16:33:03 ++++ xmlsec1-1.3.7/src/openssl/signatures.c 2025-02-12 15:32:02 +@@ -35,6 +35,7 @@ + #ifdef XMLSEC_OPENSSL_API_300 + #include + #endif /* XMLSEC_OPENSSL_API_300 */ ++#include + + #include "../cast_helpers.h" + #include "openssl_compat.h" +@@ -921,15 +922,22 @@ + "ret=%d", ret); + goto error; + } ++ ret = EVP_PKEY_CTX_set_signature_md(pKeyCtx, ctx->digest); + } else { +- ret = EVP_PKEY_verify_init(pKeyCtx); ++ if((ctx->mode == xmlSecOpenSSLEvpSignatureMode_RsaPadding) && (ctx->rsaPadding == RSA_PKCS1_PADDING)) { ++ ret = EVP_PKEY_verify_recover_init(pKeyCtx); ++ } else { ++ ret = EVP_PKEY_verify_init(pKeyCtx); ++ } + if(ret <= 0) { + xmlSecOpenSSLError2("EVP_PKEY_verify_init", xmlSecTransformGetName(transform), + "ret=%d", ret); + goto error; + } ++ if((ctx->mode != xmlSecOpenSSLEvpSignatureMode_RsaPadding) || (ctx->rsaPadding != RSA_PKCS1_PADDING)) { ++ ret = EVP_PKEY_CTX_set_signature_md(pKeyCtx, ctx->digest); ++ } + } +- ret = EVP_PKEY_CTX_set_signature_md(pKeyCtx, ctx->digest); + if(ret <= 0) { + xmlSecOpenSSLError2("EVP_PKEY_CTX_set_signature_md", xmlSecTransformGetName(transform), + "ret=%d", ret); +@@ -983,6 +991,9 @@ + xmlSecByte dgst[EVP_MAX_MD_SIZE]; + unsigned int dgstSize = sizeof(dgst); + EVP_PKEY_CTX *pKeyCtx = NULL; ++ unsigned char * recvData = NULL; ++ size_t recvDataLen = 0; ++ const unsigned char * recvDataPtr; + #if !defined(XMLSEC_NO_DSA) || !defined(XMLSEC_NO_EC) + unsigned char * fixedData = NULL; + int fixedDataLen = 0; +@@ -990,6 +1001,9 @@ + unsigned int dataLen; + int ret; + int res = -1; ++ X509_SIG * sig = NULL; ++ const X509_ALGOR *algor = NULL; ++ const ASN1_OCTET_STRING *value = NULL; + + xmlSecAssert2(xmlSecOpenSSLEvpSignatureCheckId(transform), -1); + xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); +@@ -1021,8 +1035,51 @@ + + switch(ctx->mode) { + case xmlSecOpenSSLEvpSignatureMode_RsaPadding: ++ XMLSEC_SAFE_CAST_SIZE_TO_UINT(dataSize, dataLen, goto done, xmlSecTransformGetName(transform)); ++ if(ctx->rsaPadding != RSA_PKCS1_PADDING) { ++ ret = EVP_PKEY_verify(pKeyCtx, (xmlSecByte*)data, dataLen, dgst, dgstSize); ++ break; ++ } ++ ++ ret = EVP_PKEY_verify_recover(pKeyCtx, NULL, &recvDataLen, data, dataLen); ++ if((ret <= 0) || (recvDataLen <= 0)) { ++ xmlSecOpenSSLError("EVP_PKEY_verify_recover", xmlSecTransformGetName(transform)); ++ goto done; ++ } ++ ++ recvData = OPENSSL_malloc(recvDataLen); ++ ret = EVP_PKEY_verify_recover(pKeyCtx, recvData, &recvDataLen, data, dataLen); ++ if((ret <= 0) || (recvDataLen <= 0)) { ++ xmlSecOpenSSLError("EVP_PKEY_verify_recover", xmlSecTransformGetName(transform)); ++ goto done; ++ } ++ ++ recvDataPtr = recvData; ++ sig = d2i_X509_SIG(NULL, &recvDataPtr, (long)recvDataLen); ++ if(!sig) { ++ xmlSecOpenSSLError("d2i_X509_SIG", xmlSecTransformGetName(transform)); ++ goto done; ++ } ++ ++ X509_SIG_get0(sig, &algor, &value); ++ if((algor->parameter != NULL) && (ASN1_TYPE_get(algor->parameter) != V_ASN1_NULL)) { ++ xmlSecInternalError("Signature algorithm parameter type is not ASN1 NULL", xmlSecTransformGetName(transform)); ++ goto done; ++ } ++ ++ if(EVP_MD_nid(ctx->digest) != OBJ_obj2nid(algor->algorithm)) { ++ xmlSecInternalError("Signature digest method does not match excpected digest method", xmlSecTransformGetName(transform)); ++ goto done; ++ } ++ ++ if(((const unsigned int)value->length == dgstSize) && (memcmp(value->data, dgst, dgstSize) == 0)) { ++ ret = 1; ++ } else { ++ ret = 0; ++ } ++ break; ++ + case xmlSecOpenSSLEvpSignatureMode_Gost: +- /* simple RSA or GOST padding */ + XMLSEC_SAFE_CAST_SIZE_TO_UINT(dataSize, dataLen, goto done, xmlSecTransformGetName(transform)); + ret = EVP_PKEY_verify(pKeyCtx, (xmlSecByte*)data, dataLen, dgst, dgstSize); + break; +@@ -1077,11 +1134,17 @@ + res = 0; + + done: ++ if(sig != NULL) { ++ X509_SIG_free(sig); ++ } + #if !defined(XMLSEC_NO_DSA) || !defined(XMLSEC_NO_EC) + if(fixedData != NULL) { + OPENSSL_free(fixedData); + } + #endif ++ if(recvData != NULL) { ++ OPENSSL_free(recvData); ++ } + if(pKeyCtx != NULL) { + EVP_PKEY_CTX_free(pKeyCtx); + }