diff --git a/.github/workflows/ci_new.yml b/.github/workflows/ci_new.yml index 27020ae6ab..32705387e2 100644 --- a/.github/workflows/ci_new.yml +++ b/.github/workflows/ci_new.yml @@ -35,7 +35,7 @@ jobs: - { label: "with pcre", opt: "--with-pcre" } steps: - - uses: actions/checkout@v6 +git push --force - uses: actions/checkout@v6 with: fetch-depth: 0 submodules: recursive @@ -56,7 +56,9 @@ jobs: libpcre3-dev \ bison \ flex \ - pkg-config + pkg-config \ + python3 \ + python3-venv - name: Run build preparation script @@ -206,7 +208,7 @@ jobs: - name: Install cppcheck run: | - brew install autoconf automake libtool cppcheck libmaxminddb yajl lua lmdb ssdeep + brew install autoconf automake libtool cppcheck libmaxminddb yajl lua lmdb ssdeep python3 - name: Configure project run: | @@ -256,7 +258,9 @@ jobs: libfuzzy-dev \ pcre2-utils \ bison \ - flex + flex \ + python3 \ + python3-venv - name: Run build preparation script run: ./build.sh diff --git a/Makefile.am b/Makefile.am index 7ac184b504..9ff5670620 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,12 @@ parser: cat src/parser/seclang-parser.hh | sed "s/return \*new (yyas_ ()) T (t)/return *new (yyas_ ()) T (std::move((T\&)t))/g" > src/parser/seclang-parser.hh.fix && mv src/parser/seclang-parser.hh.fix src/parser/seclang-parser.hh +CPPCHECK_EXCLUDES = \ + src/parser/seclang-parser.cc \ + src/parser/seclang-scanner.cc \ + others \ + .build-venv + cppcheck: @cppcheck -U YYSTYPE -U MBEDTLS_MD5_ALT -U MBEDTLS_SHA1_ALT \ @@ -65,8 +71,7 @@ cppcheck: --template="warning: {file},{line},{severity},{id},{message}" \ -I headers -I . -I $(top_srcdir)/others -I $(top_srcdir)/src -I $(top_srcdir)/others/mbedtls/include \ --error-exitcode=1 \ - -i "src/parser/seclang-parser.cc" -i "src/parser/seclang-scanner.cc" \ - -i others \ + $(foreach path,$(CPPCHECK_EXCLUDES),-i "$(path)") \ --std=c++17 \ --force --verbose . diff --git a/build.sh b/build.sh index 7f47f03c04..25667e53c3 100755 --- a/build.sh +++ b/build.sh @@ -1,8 +1,6 @@ #!/bin/sh - rm -rf autom4te.cache rm -f aclocal.m4 - cd src rm -f headers.mk echo "noinst_HEADERS = \\" > headers.mk @@ -24,6 +22,8 @@ ls -1 \ *.h | tr "\012" " " >> headers.mk cd ../ +./build/gen-mbedtls-sources.py + case `uname` in Darwin*) glibtoolize --force --copy ;; *) libtoolize --force --copy ;; esac autoreconf --install @@ -31,5 +31,3 @@ autoheader automake --add-missing --foreign --copy --force-missing autoconf --force rm -rf autom4te.cache - - diff --git a/build/gen-mbedtls-sources.py b/build/gen-mbedtls-sources.py new file mode 100755 index 0000000000..da435092b7 --- /dev/null +++ b/build/gen-mbedtls-sources.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +from pathlib import Path + +root = Path(__file__).resolve().parents[1] +core_dir = root / "others/mbedtls/tf-psa-crypto/core" +builtin_dir = root / "others/mbedtls/tf-psa-crypto/drivers/builtin/src" +out = root / "others/mbedtls_sources.mk" + +header = "# Auto-generated by build/gen-mbedtls-sources.py. Do not edit manually.\n" + +if not core_dir.is_dir() or not builtin_dir.is_dir(): + raise SystemExit( + "mbedTLS submodule is not initialized. Run: git submodule update --init --recursive others/mbedtls" + ) + +core = [ + p.relative_to(root / "others").as_posix() + for p in sorted(core_dir.glob("*.c")) + if p.name != "psa_crypto_driver_wrappers_no_static.c" +] +builtin = [p.relative_to(root / "others").as_posix() for p in sorted(builtin_dir.glob("*.c"))] + + +def emit(name: str, items: list[str]) -> str: + if not items: + return f"{name} =\n" + lines = [f"{name} = \\\n"] + for i, item in enumerate(items): + suffix = " \\\n" if i < len(items) - 1 else "\n" + lines.append(f" {item}{suffix}") + return "".join(lines) + +out.write_text(header + emit("MBED_PSA_CORE_SOURCES", core) + "\n" + emit("MBED_BUILTIN_SOURCES", builtin), encoding="utf-8") diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index fbf39f08d9..f07fbf034a 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -52,9 +52,118 @@ project(mbedcrypto C) set(MBEDTLS_DIR ${BASE_DIR}/others/mbedtls) -add_library(mbedcrypto STATIC ${MBEDTLS_DIR}/library/base64.c ${MBEDTLS_DIR}/library/sha1.c ${MBEDTLS_DIR}/library/md5.c ${MBEDTLS_DIR}/library/platform_util.c ${MBEDTLS_DIR}/library/constant_time.c) +set(TF_PSA_CRYPTO_CORE_DIR ${MBEDTLS_DIR}/tf-psa-crypto/core) +set(TF_PSA_CRYPTO_BUILTIN_DIR ${MBEDTLS_DIR}/tf-psa-crypto/drivers/builtin/src) +set(TF_PSA_CRYPTO_INCLUDE_DIR ${MBEDTLS_DIR}/tf-psa-crypto/include) +set(TF_PSA_CRYPTO_BUILTIN_INCLUDE_DIR ${MBEDTLS_DIR}/tf-psa-crypto/drivers/builtin/include) +set(MBEDTLS_PSA_WRAPPERS_C ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated/psa_crypto_driver_wrappers_no_static.c) +set(MBEDTLS_PSA_WRAPPERS_H ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated/psa_crypto_driver_wrappers.h) +set(MBEDTLS_TF_PSA_CONFIG_HEADERS + ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated/tf_psa_crypto_config_check_before.h + ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated/tf_psa_crypto_config_check_final.h + ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated/tf_psa_crypto_config_check_user.h +) + +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +execute_process( + COMMAND ${Python3_EXECUTABLE} -c "import venv" + RESULT_VARIABLE MBEDTLS_PYTHON_VENV_RESULT + OUTPUT_QUIET + ERROR_QUIET +) + +if(NOT MBEDTLS_PYTHON_VENV_RESULT EQUAL 0) + message(FATAL_ERROR + "python3 module 'venv' is required for mbedTLS v4 wrapper generation environment setup. " + "Please install python3-venv (or equivalent) for ${Python3_EXECUTABLE}.") +endif() + +set(MBEDTLS_PYTHON_VENV_DIR ${CMAKE_CURRENT_BINARY_DIR}/.build-venv) +if(WIN32) + set(MBEDTLS_PYTHON ${MBEDTLS_PYTHON_VENV_DIR}/Scripts/python.exe) +else() + set(MBEDTLS_PYTHON ${MBEDTLS_PYTHON_VENV_DIR}/bin/python) +endif() + +if(NOT EXISTS ${MBEDTLS_PYTHON}) + execute_process( + COMMAND ${Python3_EXECUTABLE} -m venv ${MBEDTLS_PYTHON_VENV_DIR} + RESULT_VARIABLE MBEDTLS_VENV_CREATE_RESULT + ) + if(NOT MBEDTLS_VENV_CREATE_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to create Python virtual environment: ${MBEDTLS_PYTHON_VENV_DIR}") + endif() +endif() -target_include_directories(mbedcrypto PRIVATE ${MBEDTLS_DIR}/include) +execute_process( + COMMAND ${MBEDTLS_PYTHON} -m pip --version + RESULT_VARIABLE MBEDTLS_PIP_CHECK_RESULT + OUTPUT_QUIET + ERROR_QUIET +) +if(NOT MBEDTLS_PIP_CHECK_RESULT EQUAL 0) + execute_process( + COMMAND ${MBEDTLS_PYTHON} -m ensurepip --upgrade + RESULT_VARIABLE MBEDTLS_ENSUREPIP_RESULT + ) + if(NOT MBEDTLS_ENSUREPIP_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to bootstrap pip in ${MBEDTLS_PYTHON_VENV_DIR}") + endif() +endif() + +execute_process( + COMMAND ${MBEDTLS_PYTHON} -c "import jinja2, jsonschema" + RESULT_VARIABLE MBEDTLS_PYTHON_MODULES_RESULT + OUTPUT_QUIET + ERROR_QUIET +) +if(NOT MBEDTLS_PYTHON_MODULES_RESULT EQUAL 0) + execute_process( + COMMAND ${MBEDTLS_PYTHON} -m pip install --disable-pip-version-check jinja2 jsonschema + RESULT_VARIABLE MBEDTLS_PIP_INSTALL_RESULT + ) + if(NOT MBEDTLS_PIP_INSTALL_RESULT EQUAL 0) + message(FATAL_ERROR + "Failed to install Python modules 'jinja2' and 'jsonschema' into ${MBEDTLS_PYTHON_VENV_DIR}. " + "Please verify network/package access and re-run CMake.") + endif() +endif() + +add_custom_command( + OUTPUT ${MBEDTLS_PSA_WRAPPERS_C} ${MBEDTLS_PSA_WRAPPERS_H} ${MBEDTLS_TF_PSA_CONFIG_HEADERS} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated + COMMAND ${MBEDTLS_PYTHON} ${MBEDTLS_DIR}/tf-psa-crypto/scripts/generate_driver_wrappers.py ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated + COMMAND ${CMAKE_COMMAND} -E chdir ${MBEDTLS_DIR}/tf-psa-crypto ${MBEDTLS_PYTHON} scripts/generate_config_checks.py ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated + DEPENDS + ${MBEDTLS_DIR}/tf-psa-crypto/scripts/generate_driver_wrappers.py + ${MBEDTLS_DIR}/tf-psa-crypto/scripts/generate_config_checks.py + ${MBEDTLS_DIR}/tf-psa-crypto/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja + ${MBEDTLS_DIR}/tf-psa-crypto/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja +) + +file(GLOB MBEDTLS_PSA_CORE_SOURCES CONFIGURE_DEPENDS ${TF_PSA_CRYPTO_CORE_DIR}/*.c) +list(FILTER MBEDTLS_PSA_CORE_SOURCES EXCLUDE REGEX "psa_crypto_driver_wrappers_no_static\\.c$") +file(GLOB MBEDTLS_BUILTIN_SOURCES CONFIGURE_DEPENDS ${TF_PSA_CRYPTO_BUILTIN_DIR}/*.c) + +add_library(mbedcrypto STATIC + ${MBEDTLS_PSA_CORE_SOURCES} + ${MBEDTLS_BUILTIN_SOURCES} + ${MBEDTLS_PSA_WRAPPERS_C} + ${MBEDTLS_PSA_WRAPPERS_H} + ${MBEDTLS_TF_PSA_CONFIG_HEADERS} +) + +target_include_directories(mbedcrypto PRIVATE + ${MBEDTLS_DIR}/include + ${TF_PSA_CRYPTO_INCLUDE_DIR} + ${TF_PSA_CRYPTO_CORE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated + ${TF_PSA_CRYPTO_BUILTIN_INCLUDE_DIR} + ${TF_PSA_CRYPTO_BUILTIN_DIR} +) + +target_link_libraries(mbedcrypto PRIVATE bcrypt) # get mbedtls version with git describe execute_process( @@ -137,7 +246,17 @@ file(GLOB_RECURSE libModSecuritySources ${BASE_DIR}/src/*.cc) add_library(libModSecurity SHARED ${libModSecuritySources}) target_compile_definitions(libModSecurity PRIVATE WITH_PCRE2) -target_include_directories(libModSecurity PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others ${MBEDTLS_DIR}/include) +target_include_directories(libModSecurity PRIVATE + ${BASE_DIR} + ${BASE_DIR}/headers + ${BASE_DIR}/others + ${MBEDTLS_DIR}/include + ${TF_PSA_CRYPTO_INCLUDE_DIR} + ${TF_PSA_CRYPTO_CORE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated + ${TF_PSA_CRYPTO_BUILTIN_INCLUDE_DIR} + ${TF_PSA_CRYPTO_BUILTIN_DIR} +) target_link_libraries(libModSecurity PRIVATE pcre2::pcre2 libinjection mbedcrypto Poco::Poco Iphlpapi.lib) macro(add_package_dependency project compile_definition link_library flag) @@ -164,7 +283,17 @@ project(libModSecurityTests) function(setTestTargetProperties executable) target_compile_definitions(${executable} PRIVATE WITH_PCRE2) - target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers) + target_include_directories(${executable} PRIVATE + ${BASE_DIR} + ${BASE_DIR}/headers + ${BASE_DIR}/others + ${MBEDTLS_DIR}/include + ${TF_PSA_CRYPTO_INCLUDE_DIR} + ${TF_PSA_CRYPTO_CORE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/mbedtls_generated + ${TF_PSA_CRYPTO_BUILTIN_INCLUDE_DIR} + ${TF_PSA_CRYPTO_BUILTIN_DIR} + ) target_link_libraries(${executable} PRIVATE libModSecurity pcre2::pcre2 dirent::dirent) add_package_dependency(${executable} WITH_YAJL yajl::yajl HAVE_YAJL) endfunction() diff --git a/configure.ac b/configure.ac index 03295be063..59020f866a 100644 --- a/configure.ac +++ b/configure.ac @@ -57,7 +57,7 @@ AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_MKDIR_P PKG_PROG_PKG_CONFIG - +AC_PATH_PROG([PYTHON3], [python3], [:]) # Set C++ standard version and check if compiler supports it. AX_CXX_COMPILE_STDCXX(17, noext, mandatory) @@ -84,7 +84,7 @@ AC_DEFUN([LIBINJECTION_VERSION], m4_esyscmd_s(cd "others/libinjection" && git de AC_SUBST([LIBINJECTION_VERSION]) # Check for Mbed TLS -if ! test -f "${srcdir}/others/mbedtls/library/base64.c"; then +if ! test -f "${srcdir}/others/mbedtls/tf-psa-crypto/drivers/builtin/src/base64.c"; then AC_MSG_ERROR([\ @@ -100,6 +100,94 @@ AC_MSG_ERROR([\ ]) fi + + +if test "x$PYTHON3" = "x:"; then +AC_MSG_ERROR([\ + + python3 was not found. + + Mbed TLS v4 integration requires python3 + venv to generate PSA wrapper and + config-check sources in an isolated environment. + + Please install python3 (including the venv module) and re-run build.sh/configure. + + ]) +fi + +if ! "$PYTHON3" -c "import venv" >/dev/null 2>&1; then +AC_MSG_ERROR([\ + + python3 module 'venv' is not available. + + ModSecurity's mbedTLS v4 build creates an isolated Python environment + automatically and requires python3-venv support. + + Please install python3-venv (or your platform equivalent) and re-run configure. + + ]) +fi + +MBEDTLS_PYTHON_VENV_PROBE_DIR=`mktemp -d "${TMPDIR-/tmp}/modsecurity-python-venv.XXXXXX" 2>/dev/null` +if test "x$MBEDTLS_PYTHON_VENV_PROBE_DIR" = "x" || test ! -d "$MBEDTLS_PYTHON_VENV_PROBE_DIR"; then +AC_MSG_ERROR([\ + + Failed to create a temporary directory to validate python3 venv support. + + Please ensure mktemp works and the temporary directory is writable, then re-run configure. + + ]) +fi + +if ! "$PYTHON3" -m venv "$MBEDTLS_PYTHON_VENV_PROBE_DIR" >/dev/null 2>&1; then + rm -rf "$MBEDTLS_PYTHON_VENV_PROBE_DIR" +AC_MSG_ERROR([\ + + python3 was found, but creating a virtual environment failed. + + ModSecurity's mbedTLS v4 build requires a working python3 venv implementation. + On Debian/Ubuntu this usually means the package 'python3-venv' is missing. + + Please install python3-venv (for example: apt install python3-venv) and re-run configure. + + ]) +fi + +rm -rf "$MBEDTLS_PYTHON_VENV_PROBE_DIR" + +MBEDTLS_PYTHON_VENV_DIR="`pwd`/.build-venv" +MBEDTLS_PYTHON="$MBEDTLS_PYTHON_VENV_DIR/bin/python" + +if test ! -x "$MBEDTLS_PYTHON"; then + AC_MSG_NOTICE([Creating Python virtual environment for mbedTLS v4 in $MBEDTLS_PYTHON_VENV_DIR]) + if ! "$PYTHON3" -m venv "$MBEDTLS_PYTHON_VENV_DIR" >/dev/null 2>&1; then + AC_MSG_ERROR([Failed to create Python virtual environment in $MBEDTLS_PYTHON_VENV_DIR. +Please verify that python3-venv is installed and that the build directory is writable.]) + fi +fi + +if ! "$MBEDTLS_PYTHON" -m pip --version >/dev/null 2>&1; then + if ! "$MBEDTLS_PYTHON" -m ensurepip --upgrade >/dev/null 2>&1; then + AC_MSG_ERROR([Failed to bootstrap pip inside $MBEDTLS_PYTHON_VENV_DIR.]) + fi +fi + +if ! "$MBEDTLS_PYTHON" -c "import jinja2, jsonschema" >/dev/null 2>&1; then + AC_MSG_NOTICE([Installing Python build dependencies (jinja2, jsonschema) into $MBEDTLS_PYTHON_VENV_DIR]) + if ! "$MBEDTLS_PYTHON" -m pip install --disable-pip-version-check jinja2 jsonschema >/dev/null 2>&1; then +AC_MSG_ERROR([\ + + Failed to install Python modules 'jinja2' and 'jsonschema' into: + $MBEDTLS_PYTHON_VENV_DIR + + Please verify network/package access and re-run configure. + + ]) + fi +fi + +AC_SUBST([MBEDTLS_PYTHON]) + # Mbed TLS version AC_DEFUN([MBEDTLS_VERSION], m4_esyscmd_s(cd "others/mbedtls" && git describe && cd ../..)) @@ -296,6 +384,25 @@ if test $buildParser = true; then AC_PATH_PROG([BISON], [bison]) test "x$BISON" = "x" && AC_MSG_ERROR([bison is needed to build ModSecurity]) + + BISON_VERSION=`$BISON --version 2>/dev/null | head -n 1 | sed 's/.* //g'` + AC_SUBST([BISON_VERSION]) + if ! awk 'BEGIN { + split(ARGV[1], current, "."); + split(ARGV[2], required, "."); + for (i = 1; i <= 3; ++i) { + c = (current[i] == "") ? 0 : current[i]; + r = (required[i] == "") ? 0 : required[i]; + if ((c + 0) > (r + 0)) exit 0; + if ((c + 0) < (r + 0)) exit 1; + } + exit 0; + }' "$BISON_VERSION" "3.0.2"; then + AC_MSG_ERROR([bison >= 3.0.2 is required for --enable-parser-generation. +Install a newer bison or disable parser generation to use the checked-in parser sources.]) + fi + + AC_PATH_PROG([YACC_INST], $YACC) if test ! -f "$srcdir/gram.c"; then if test -z "$YACC_INST"; then @@ -349,6 +456,15 @@ case $assertions in esac GLOBAL_CPPFLAGS="$GLOBAL_CPPFLAGS $ASSERTIONS_CPPCFLAGS" +MBEDTLS_CPPFLAGS='-DMBEDTLS_CONFIG_FILE=\"mbedtls/mbedtls_config.h\" \ +-I$(top_srcdir)/others/mbedtls/include \ +-I$(top_srcdir)/others/mbedtls/tf-psa-crypto/include \ +-I$(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/include \ +-I$(top_srcdir)/others/mbedtls/include \ +-I$(top_srcdir)/others/mbedtls/tf-psa-crypto/core \ +-I$(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/src' +GLOBAL_CPPFLAGS="$GLOBAL_CPPFLAGS $MBEDTLS_CPPFLAGS" + AC_SUBST(GLOBAL_LDADD) AC_SUBST(GLOBAL_CPPFLAGS) diff --git a/others/Makefile.am b/others/Makefile.am index b102a0330c..45be584a60 100644 --- a/others/Makefile.am +++ b/others/Makefile.am @@ -15,19 +15,60 @@ noinst_HEADERS = \ libinjection/src/libinjection_sqli.h \ libinjection/src/libinjection_sqli_data.h \ libinjection/src/libinjection_xss.h \ - mbedtls/include/mbedtls/base64.h \ - mbedtls/include/mbedtls/check_config.h \ + mbedtls/tf-psa-crypto/include/mbedtls/base64.h \ + mbedtls/tf-psa-crypto/drivers/builtin/src/check_crypto_config.h \ mbedtls/include/mbedtls/mbedtls_config.h \ - mbedtls/include/mbedtls/md5.h \ - mbedtls/include/mbedtls/platform.h \ - mbedtls/include/mbedtls/sha1.h + mbedtls/tf-psa-crypto/drivers/builtin/include/mbedtls/private/md5.h \ + mbedtls/tf-psa-crypto/include/mbedtls/platform.h \ + mbedtls/tf-psa-crypto/drivers/builtin/include/mbedtls/private/sha1.h + +include $(top_srcdir)/others/mbedtls_sources.mk + +MBED_PSA_CORE_SOURCES += \ + $(MBED_GENERATED_PSA_WRAPPERS_C) + +MBEDTLS_PY = @MBEDTLS_PYTHON@ +MBED_GENERATED_CORE_DIR = $(builddir)/mbedtls-generated/core +MBED_GENERATED_PSA_WRAPPERS_H = $(MBED_GENERATED_CORE_DIR)/psa_crypto_driver_wrappers.h +MBED_GENERATED_PSA_WRAPPERS_C = $(MBED_GENERATED_CORE_DIR)/psa_crypto_driver_wrappers_no_static.c +MBED_GENERATED_TF_PSA_CONFIG_HDRS = \ + $(MBED_GENERATED_CORE_DIR)/tf_psa_crypto_config_check_before.h \ + $(MBED_GENERATED_CORE_DIR)/tf_psa_crypto_config_check_final.h \ + $(MBED_GENERATED_CORE_DIR)/tf_psa_crypto_config_check_user.h +MBED_GENERATED_STAMP = $(MBED_GENERATED_CORE_DIR)/.generated.stamp + +BUILT_SOURCES = \ + $(MBED_GENERATED_PSA_WRAPPERS_H) \ + $(MBED_GENERATED_PSA_WRAPPERS_C) \ + $(MBED_GENERATED_TF_PSA_CONFIG_HDRS) + +CLEANFILES = \ + $(MBED_GENERATED_PSA_WRAPPERS_H) \ + $(MBED_GENERATED_PSA_WRAPPERS_C) \ + $(MBED_GENERATED_TF_PSA_CONFIG_HDRS) \ + $(MBED_GENERATED_STAMP) + +$(MBED_GENERATED_PSA_WRAPPERS_H) $(MBED_GENERATED_PSA_WRAPPERS_C) $(MBED_GENERATED_TF_PSA_CONFIG_HDRS): $(MBED_GENERATED_STAMP) + +$(MBED_GENERATED_STAMP): + $(AM_V_at)mkdir -p $(MBED_GENERATED_CORE_DIR) + $(AM_V_GEN)$(MBEDTLS_PY) $(top_srcdir)/others/mbedtls/tf-psa-crypto/scripts/generate_driver_wrappers.py $(MBED_GENERATED_CORE_DIR) + $(AM_V_GEN)cd $(top_srcdir)/others/mbedtls/tf-psa-crypto && \ + $(MBEDTLS_PY) scripts/generate_config_checks.py $(abspath $(MBED_GENERATED_CORE_DIR)) + $(AM_V_at)touch $(MBED_GENERATED_STAMP) libmbedtls_la_SOURCES = \ - mbedtls/library/base64.c \ - mbedtls/library/md5.c \ - mbedtls/library/sha1.c \ - mbedtls/library/platform_util.c + $(MBED_PSA_CORE_SOURCES) \ + $(MBED_BUILTIN_SOURCES) + +libmbedtls_la_CPPFLAGS = \ + -DMBEDTLS_CONFIG_FILE=\"mbedtls/mbedtls_config.h\" \ + -I$(top_srcdir)/others/mbedtls/include \ + -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/include \ + -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/core \ + -I$(top_builddir)/others/mbedtls-generated/core \ + -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/include \ + -I$(top_srcdir)/others/mbedtls/tf-psa-crypto/drivers/builtin/src -libmbedtls_la_CFLAGS = -DMBEDTLS_CONFIG_FILE=\"mbedtls/mbedtls_config.h\" -I$(top_srcdir)/others/mbedtls/include -libmbedtls_la_CPPFLAGS = +#libmbedtls_la_CPPFLAGS = libmbedtls_la_LIBADD = diff --git a/others/mbedtls b/others/mbedtls index 2ca6c285a0..ec4044008d 160000 --- a/others/mbedtls +++ b/others/mbedtls @@ -1 +1 @@ -Subproject commit 2ca6c285a0dd3f33982dd57299012dacab1ff206 +Subproject commit ec4044008d2d069da38288bc76b0fee34ec78646 diff --git a/others/mbedtls_sources.mk b/others/mbedtls_sources.mk new file mode 100644 index 0000000000..24e3d5e323 --- /dev/null +++ b/others/mbedtls_sources.mk @@ -0,0 +1,77 @@ +# Auto-generated by build/gen-mbedtls-sources.py. Do not edit manually. +MBED_PSA_CORE_SOURCES = \ + mbedtls/tf-psa-crypto/core/psa_crypto.c \ + mbedtls/tf-psa-crypto/core/psa_crypto_client.c \ + mbedtls/tf-psa-crypto/core/psa_crypto_slot_management.c \ + mbedtls/tf-psa-crypto/core/psa_crypto_storage.c \ + mbedtls/tf-psa-crypto/core/psa_its_file.c \ + mbedtls/tf-psa-crypto/core/tf_psa_crypto_config.c \ + mbedtls/tf-psa-crypto/core/tf_psa_crypto_version.c + +MBED_BUILTIN_SOURCES = \ + mbedtls/tf-psa-crypto/drivers/builtin/src/aes.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/aesce.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/aesni.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/aria.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/asn1parse.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/asn1write.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/base64.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/bignum.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/bignum_core.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/bignum_mod.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/bignum_mod_raw.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/block_cipher.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/camellia.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ccm.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/chacha20.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/chachapoly.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/cipher.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/cipher_wrap.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/cmac.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/constant_time.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ctr_drbg.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ecdh.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ecdsa.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ecjpake.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ecp.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ecp_curves.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ecp_curves_new.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/entropy.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/entropy_poll.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/gcm.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/hmac_drbg.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/lmots.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/lms.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/md.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/md5.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/memory_buffer_alloc.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/nist_kw.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/oid.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pem.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pk.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pk_ecc.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pk_rsa.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pk_wrap.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pkcs5.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pkparse.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/pkwrite.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/platform.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/platform_util.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/poly1305.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_aead.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_cipher.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_ffdh.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_hash.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_mac.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_pake.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/psa_util.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/ripemd160.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/rsa.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/rsa_alt_helpers.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha1.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha256.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha3.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/sha512.c \ + mbedtls/tf-psa-crypto/drivers/builtin/src/threading.c diff --git a/src/unique_id.cc b/src/unique_id.cc index 890188e990..8762795d34 100644 --- a/src/unique_id.cc +++ b/src/unique_id.cc @@ -56,7 +56,8 @@ #endif #include -#include "src/utils/sha1.h" +/*#include "src/utils/sha1.h"*/ +#include "src/utils/sha256.h" namespace modsecurity { @@ -72,7 +73,7 @@ void UniqueId::fillUniqueId() { data = macAddress + name; - this->uniqueId_str = Utils::Sha1::hexdigest(data); + this->uniqueId_str = Utils::Sha256::hexdigest(data); } // Based on: diff --git a/src/utils/md5.h b/src/utils/md5.h index 68f5d748e4..834039cc3a 100644 --- a/src/utils/md5.h +++ b/src/utils/md5.h @@ -16,17 +16,37 @@ #ifndef SRC_UTILS_MD5_H_ #define SRC_UTILS_MD5_H_ -#include "src/utils/sha1.h" -#include "mbedtls/md5.h" +#include "src/utils/sha1.h" // uses DigestImpl + detail::ensure_psa_init() #include -namespace modsecurity::Utils { - +#include // optional (since sha1.h already includes it), but ok -class Md5 : public DigestImpl<&mbedtls_md5, 16> { -}; +namespace modsecurity::Utils { +// PSA wrapper with legacy signature +inline int modsec_psa_md5(const unsigned char *input, + size_t ilen, + unsigned char output[16]) +{ + if (!detail::ensure_psa_init()) { + return -1; + } + + size_t out_len = 0; + psa_status_t status = psa_hash_compute( + PSA_ALG_MD5, + input, + ilen, + output, + 16, + &out_len + ); + + return (status == PSA_SUCCESS && out_len == 16) ? 0 : -1; +} + +class Md5 : public DigestImpl<&modsec_psa_md5, 16> {}; } // namespace modsecurity::Utils -#endif // SRC_UTILS_MD5_H_ \ No newline at end of file +#endif // SRC_UTILS_MD5_H_ diff --git a/src/utils/sha1.h b/src/utils/sha1.h index a40d7fa1c8..3c9ee69555 100644 --- a/src/utils/sha1.h +++ b/src/utils/sha1.h @@ -16,60 +16,104 @@ #ifndef SRC_UTILS_SHA1_H_ #define SRC_UTILS_SHA1_H_ +#include +#include +#include +#include #include -#include +#include #include "src/utils/string.h" -#include "mbedtls/sha1.h" +#include namespace modsecurity::Utils { +namespace detail { -using DigestOp = int (*)(const unsigned char *, size_t, unsigned char []); +// Thread-safe PSA initialization shared by all digests +inline bool ensure_psa_init() { + static std::once_flag once; + static psa_status_t init_status = PSA_ERROR_GENERIC_ERROR; + std::call_once(once, []() { init_status = psa_crypto_init(); }); -template + return init_status == PSA_SUCCESS; +} + +} // namespace detail + +// C-friendly digest function signature (matches legacy wrappers like modsec_psa_md5) +template +using DigestOp = int (*)(const unsigned char* input, + std::size_t input_len, + unsigned char* output); + +// Generic digest implementation +template class DigestImpl { public: - static std::string digest(const std::string& input) { - return digestHelper(input, [](const auto digest) { - return std::string(digest); + return digestHelper(input, [](std::string_view d) { + return std::string{d}; }); } static void digestReplace(std::string& value) { - digestHelper(value, [&value](const auto digest) mutable { - value = digest; - }); + value = digest(value); } - static std::string hexdigest(const std::string &input) { - return digestHelper(input, [](const auto digest) { - return utils::string::string_to_hex(digest); + static std::string hexdigest(const std::string& input) { + return digestHelper(input, [](std::string_view d) { + return utils::string::string_to_hex(d); }); } -private: + private: + template + static auto digestHelper(const std::string& input, ConvertOp convertOp) + -> decltype(convertOp(std::string_view{})) { - template - static auto digestHelper(const std::string &input, - ConvertOp convertOp) -> auto { - char digest[DigestSize]; + std::array out{}; + const std::string_view sv{input}; - const auto ret = (*digestOp)(reinterpret_cast(input.c_str()), - input.size(), reinterpret_cast(digest)); - assert(ret == 0); + const auto* in_ptr = + reinterpret_cast(sv.data()); + const std::size_t in_len = sv.size(); - return convertOp(std::string_view(digest, DigestSize)); + if (DigestFn(in_ptr, in_len, out.data()) != 0) { + return convertOp(std::string_view{}); + } + + std::string raw(DigestSize, '\0'); + std::memcpy(raw.data(), out.data(), DigestSize); + return convertOp(std::string_view{raw}); } }; +// PSA wrapper for SHA-1 (0 = success, non-zero = error) +inline int modsec_psa_sha1(const unsigned char* input, + std::size_t ilen, + unsigned char* output) { + if (!detail::ensure_psa_init()) { + return -1; + } -class Sha1 : public DigestImpl<&mbedtls_sha1, 20> { -}; + size_t out_len = 0; + psa_status_t status = psa_hash_compute( + PSA_ALG_SHA_1, + input, + ilen, + output, + 20, + &out_len + ); + return (status == PSA_SUCCESS && out_len == 20) ? 0 : -1; +} + +class Sha1 : public DigestImpl<&modsec_psa_sha1, 20> {}; } // namespace modsecurity::Utils #endif // SRC_UTILS_SHA1_H_ + diff --git a/src/utils/sha256.h b/src/utils/sha256.h new file mode 100644 index 0000000000..401c8aa340 --- /dev/null +++ b/src/utils/sha256.h @@ -0,0 +1,50 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + + +#ifndef SRC_UTILS_SHA256_H_ +#define SRC_UTILS_SHA256_H_ + +#include "src/utils/sha1.h" // provides DigestImpl + detail::ensure_psa_init() +#include + +namespace modsecurity::Utils { + +inline int modsec_psa_sha256(const unsigned char *input, + size_t ilen, + unsigned char output[32]) +{ + if (!detail::ensure_psa_init()) { + return -1; + } + + size_t out_len = 0; + psa_status_t status = psa_hash_compute( + PSA_ALG_SHA_256, + input, + ilen, + output, + 32, + &out_len + ); + + return (status == PSA_SUCCESS && out_len == 32) ? 0 : -1; +} + +class Sha256 : public DigestImpl<&modsec_psa_sha256, 32> {}; + +} // namespace modsecurity::Utils + +#endif // SRC_UTILS_SHA256_H_ diff --git a/test/test-cases/secrules-language-tests b/test/test-cases/secrules-language-tests index a3d4405e5a..c6e8802366 160000 --- a/test/test-cases/secrules-language-tests +++ b/test/test-cases/secrules-language-tests @@ -1 +1 @@ -Subproject commit a3d4405e5a2c90488c387e589c5534974575e35b +Subproject commit c6e8802366ec3182b8c2612e23d14e19e3545b47