Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion contrib/openssl-cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ docker cp $id:$lib_dir/build/ssl/libssl.a $OUTPUT_DIR
docker cp $id:$lib_dir/build/crypto/libcrypto.a $OUTPUT_DIR
docker cp $id:$lib_dir/include $OUTPUT_DIR

# Extract pre-built test harness libraries (symbol-localized, with libstdc++ baked in)
docker cp $id:/harness-output/libawslc_shim.a $OUTPUT_DIR
docker cp $id:/harness-output/libawslc_handshaker.a $OUTPUT_DIR
docker cp $id:/harness-output/libawslc_acvp_server.a $OUTPUT_DIR

docker rm $id"
)

Expand Down Expand Up @@ -70,7 +75,12 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${AWSLC_BINARIES_DIR

add_custom_target(build-awslc
COMMENT "Build AWS-LC in FIPS mode with docker"
DEPENDS ${AWSLC_BINARIES_DIR}/libssl.a ${AWSLC_BINARIES_DIR}/libcrypto.a
DEPENDS
${AWSLC_BINARIES_DIR}/libssl.a
${AWSLC_BINARIES_DIR}/libcrypto.a
${AWSLC_BINARIES_DIR}/libawslc_shim.a
${AWSLC_BINARIES_DIR}/libawslc_handshaker.a
${AWSLC_BINARIES_DIR}/libawslc_acvp_server.a
)

if(ARCH_AARCH64)
Expand All @@ -83,7 +93,20 @@ add_custom_command(
OUTPUT
"${AWSLC_BUILD_DIR}/output/libssl.a"
"${AWSLC_BUILD_DIR}/output/libcrypto.a"
"${AWSLC_BUILD_DIR}/output/libawslc_shim.a"
"${AWSLC_BUILD_DIR}/output/libawslc_handshaker.a"
"${AWSLC_BUILD_DIR}/output/libawslc_acvp_server.a"
COMMENT "Building AWS-LC in FIPS mode using docker"
# Copy test harness build inputs into the Docker context directory
COMMAND ${CMAKE_COMMAND} -E copy
${ClickHouse_SOURCE_DIR}/programs/ssl-common/posix_spawn_2.c
${AWSLC_BUILD_DIR}/posix_spawn_2.c
COMMAND ${CMAKE_COMMAND} -E copy
${ClickHouse_SOURCE_DIR}/programs/ssl-common/glibc_compat.c
${AWSLC_BUILD_DIR}/glibc_compat.c
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/build_test_harness.sh
${AWSLC_BUILD_DIR}/build_test_harness.sh
COMMAND bash -c "chmod +x ${AWSLC_BUILD_DIR}/build_awclc_fips.sh"
COMMAND bash -c "${AWSLC_BUILD_DIR}/build_awclc_fips.sh ${AWSLC_BINARIES_DIR} ${DOCKERFILE_PATH}"
WORKING_DIRECTORY ${AWSLC_BUILD_DIR}
Expand All @@ -92,6 +115,9 @@ add_custom_command(
${AWSLC_BUILD_DIR}/build_awclc_fips.sh
${AWSLC_BUILD_DIR}/check_version.c
${DOCKERFILE_PATH}
${ClickHouse_SOURCE_DIR}/programs/ssl-common/posix_spawn_2.c
${ClickHouse_SOURCE_DIR}/programs/ssl-common/glibc_compat.c
${CMAKE_CURRENT_SOURCE_DIR}/build_test_harness.sh
)

add_library(crypto UNKNOWN IMPORTED GLOBAL)
Expand Down Expand Up @@ -130,6 +156,45 @@ target_compile_options(ssl INTERFACE
target_compile_options(global-group INTERFACE "-Wno-deprecated-declarations")
target_compile_options(global-group INTERFACE "-Wno-poison-system-directories")

# ── Test harness IMPORTED libraries ──────────────────────────────────────────
# These archives are built inside Docker (build_test_harness.sh), partially
# linked with libstdc++ via `ld -r`, and symbol-localized so only the entry
# point is globally visible. No --allow-multiple-definition needed.

add_library(awslc_shim STATIC IMPORTED GLOBAL)
add_dependencies(awslc_shim build-awslc)
set_target_properties(awslc_shim PROPERTIES
IMPORTED_LOCATION "${AWSLC_BINARIES_DIR}/libawslc_shim.a")

add_library(awslc_handshaker STATIC IMPORTED GLOBAL)
add_dependencies(awslc_handshaker build-awslc)
set_target_properties(awslc_handshaker PROPERTIES
IMPORTED_LOCATION "${AWSLC_BINARIES_DIR}/libawslc_handshaker.a")

add_library(awslc_acvp_server STATIC IMPORTED GLOBAL)
add_dependencies(awslc_acvp_server build-awslc)
set_target_properties(awslc_acvp_server PROPERTIES
IMPORTED_LOCATION "${AWSLC_BINARIES_DIR}/libawslc_acvp_server.a")

# ── Test harness program libraries ───────────────────────────────────────────
# Linked into the main clickhouse binary via clickhouse_program_install()
# in programs/CMakeLists.txt. The entry-point .cpp files stay in programs/.

add_library(clickhouse-ssl-shim-lib
${ClickHouse_SOURCE_DIR}/programs/ssl-shim/SslShim.cpp)
target_link_libraries(clickhouse-ssl-shim-lib PRIVATE awslc_shim ssl crypto)
add_dependencies(clickhouse-ssl-shim-lib build-awslc)

add_library(clickhouse-ssl-handshaker-lib
${ClickHouse_SOURCE_DIR}/programs/ssl-handshaker/SslHandshaker.cpp)
target_link_libraries(clickhouse-ssl-handshaker-lib PRIVATE awslc_handshaker ssl crypto)
add_dependencies(clickhouse-ssl-handshaker-lib build-awslc)

add_library(clickhouse-acvp-server-lib
${ClickHouse_SOURCE_DIR}/programs/acvp-server/AcvpServer.cpp)
target_link_libraries(clickhouse-acvp-server-lib PRIVATE awslc_acvp_server crypto)
add_dependencies(clickhouse-acvp-server-lib build-awslc)

else() # FIPS_CLICKHOUSE


Expand Down
6 changes: 6 additions & 0 deletions contrib/openssl-cmake/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ RUN test $(/aws-lc-AWS-LC-FIPS-2.0.0/build/tool/bssl isfips) = 1

# execute all test
RUN find /aws-lc-AWS-LC-FIPS-2.0.0/build -iname '*test*' -type f -executable -print -exec {} \;

# Build test harness libraries for ClickHouse FIPS testing integration
COPY posix_spawn_2.c glibc_compat.c /tmp/
COPY build_test_harness.sh /tmp/
RUN chmod +x /tmp/build_test_harness.sh && \
/tmp/build_test_harness.sh /aws-lc-AWS-LC-FIPS-2.0.0 /harness-output
6 changes: 6 additions & 0 deletions contrib/openssl-cmake/Dockerfile.aarch64
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ RUN test $(/aws-lc-AWS-LC-FIPS-2.0.0/build/tool/bssl isfips) = 1

# execute all test
RUN find /aws-lc-AWS-LC-FIPS-2.0.0/build -iname '*test*' -type f -executable -print -exec {} \;

# Build test harness libraries for ClickHouse FIPS testing integration
COPY posix_spawn_2.c glibc_compat.c /tmp/
COPY build_test_harness.sh /tmp/
RUN chmod +x /tmp/build_test_harness.sh && \
/tmp/build_test_harness.sh /aws-lc-AWS-LC-FIPS-2.0.0 /harness-output
104 changes: 104 additions & 0 deletions contrib/openssl-cmake/build_test_harness.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/bin/bash
# Build test harness static libraries for ClickHouse FIPS testing integration.
#
# Each library is partially linked with libstdc++ via `ld -r` and then all
# symbols are prefixed with __awslc_ using `objcopy --prefix-symbols`.
# Undefined symbols (libssl/libcrypto/libc refs) and the entry point are
# restored to their original names via `--redefine-syms`.
#
# This prevents libstdc++ symbols from colliding with ClickHouse's libc++
# at final link time, while keeping COMDAT groups intact (localizing COMDAT
# key symbols would cause lld to discard their sections).
#
# Usage: build_test_harness.sh <awslc-src-dir> <output-dir>
set -ex

SRC=${1:?usage: build_test_harness.sh <awslc-src-dir> <output-dir>}
OUTDIR=${2:?usage: build_test_harness.sh <awslc-src-dir> <output-dir>}
mkdir -p "$OUTDIR"

CXXFLAGS="-std=c++17 -fPIC -g -O2 -fno-exceptions -w"
CFLAGS="-fPIC -O2 -w"
INC="-I$SRC/include -I$SRC -I$SRC/ssl/test"
STDCXX=$(c++ -print-file-name=libstdc++.a)
PREFIX="__awslc_"

# build_target <name> <entry_grep> <obj_dir>
# Partial-links .o files in <obj_dir> with libstdc++, prefixes all symbols,
# then restores undefined refs and entry point to original names.
build_target() {
local name=$1 entry_grep=$2 obj_dir=$3
ld -r -o "$obj_dir/combined.o" "$obj_dir"/*.o "$STDCXX"

# Collect undefined symbols — these reference external libraries
# (libssl, libcrypto, libc, pthreads) and must keep their original names.
nm -u "$obj_dir/combined.o" | awk 'NF>=2{print $NF}' | sort -u > "$obj_dir/undef.txt"

# Find entry point symbol
nm "$obj_dir/combined.o" | awk "/T.*${entry_grep}/{print \$3}" > "$obj_dir/entry.txt"

# Build redefine map: after --prefix-symbols adds the prefix,
# restore undefined symbols and entry point to original names.
awk -v p="$PREFIX" '{print p $0 " " $0}' "$obj_dir/undef.txt" > "$obj_dir/redefine.txt"
awk -v p="$PREFIX" '{print p $0 " " $0}' "$obj_dir/entry.txt" >> "$obj_dir/redefine.txt"

# Collect defined symbols — only these need weakening (to avoid
# duplicate-definition errors when multiple archives pull the same
# libstdc++ members). Undefined symbols must stay strong so the
# linker errors out if they cannot be resolved, instead of silently
# binding them to NULL.
# Names are prefixed to match post-pass-1 state.
nm --defined-only "$obj_dir/combined.o" | awk -v p="$PREFIX" \
'NF>=3{print p $NF}' | sort -u > "$obj_dir/weaken.txt"

# Two passes: objcopy applies --redefine-syms BEFORE --prefix-symbols
# in a single invocation, so we must split them.
# Pass 1: prefix every symbol.
objcopy --prefix-symbols="$PREFIX" "$obj_dir/combined.o"
# Pass 2: restore undefined refs + entry point to original names,
# and weaken only defined symbols.
objcopy --redefine-syms="$obj_dir/redefine.txt" \
--weaken-symbols="$obj_dir/weaken.txt" "$obj_dir/combined.o"

ar rcs "$OUTDIR/lib${name}.a" "$obj_dir/combined.o"
rm -rf "$obj_dir"
}

# --- ssl-shim ---
OBJ=$(mktemp -d)
for f in async_bio bssl_shim handshake_util mock_quic_transport \
packeted_bio settings_writer ssl_transfer test_config test_state; do
EXTRA="-Dposix_spawn=__ssl_posix_spawn"
[ "$f" = "bssl_shim" ] && EXTRA="$EXTRA -Dmain=bssl_shim_main"
c++ $CXXFLAGS $INC $EXTRA -c "$SRC/ssl/test/$f.cc" -o "$OBJ/$f.o"
done
c++ $CXXFLAGS $INC -Dposix_spawn=__ssl_posix_spawn \
-c "$SRC/crypto/test/test_util.cc" -o "$OBJ/test_util.o"
cc $CFLAGS -c /tmp/posix_spawn_2.c -o "$OBJ/posix_spawn_2.o"
cc $CFLAGS -c /tmp/glibc_compat.c -o "$OBJ/glibc_compat.o"
build_target awslc_shim bssl_shim_main "$OBJ"

# --- ssl-handshaker ---
OBJ=$(mktemp -d)
for f in async_bio handshake_util handshaker mock_quic_transport \
packeted_bio settings_writer test_config test_state; do
EXTRA="-Dposix_spawn=__ssl_posix_spawn"
[ "$f" = "handshaker" ] && EXTRA="$EXTRA -Dmain=handshaker_main"
c++ $CXXFLAGS $INC $EXTRA -c "$SRC/ssl/test/$f.cc" -o "$OBJ/$f.o"
done
c++ $CXXFLAGS $INC -Dposix_spawn=__ssl_posix_spawn \
-c "$SRC/crypto/test/test_util.cc" -o "$OBJ/test_util.o"
cc $CFLAGS -c /tmp/posix_spawn_2.c -o "$OBJ/posix_spawn_2.o"
cc $CFLAGS -c /tmp/glibc_compat.c -o "$OBJ/glibc_compat.o"
build_target awslc_handshaker handshaker_main "$OBJ"

# --- acvp-server ---
OBJ=$(mktemp -d)
ACVP_DIR="$SRC/util/fipstools/acvp/modulewrapper"
c++ $CXXFLAGS -I"$ACVP_DIR" -I"$SRC/include" -I"$SRC" \
-Dmain=acvp_modulewrapper_main \
-c "$ACVP_DIR/main.cc" -o "$OBJ/main.o"
c++ $CXXFLAGS -I"$ACVP_DIR" -I"$SRC/include" -I"$SRC" \
-c "$ACVP_DIR/modulewrapper.cc" -o "$OBJ/modulewrapper.o"
cc $CFLAGS -c /tmp/glibc_compat.c -o "$OBJ/glibc_compat.o"
build_target awslc_acvp_server acvp_modulewrapper_main "$OBJ"
16 changes: 16 additions & 0 deletions programs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ else()
message(STATUS "ClickHouse keeper-client mode: OFF")
endif()

if (FIPS_CLICKHOUSE AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(ENABLE_CLICKHOUSE_SSL_SHIM 1)
set(ENABLE_CLICKHOUSE_SSL_HANDSHAKER 1)
set(ENABLE_CLICKHOUSE_ACVP_SERVER 1)
endif()

configure_file (config_tools.h.in ${CONFIG_INCLUDE_PATH}/config_tools.h)

macro(clickhouse_target_link_split_lib target name)
Expand Down Expand Up @@ -225,6 +231,16 @@ if (ENABLE_CLICKHOUSE_KEEPER_CLIENT)
list(APPEND CLICKHOUSE_BUNDLE clickhouse-keeper-client)
endif ()

if (ENABLE_CLICKHOUSE_SSL_SHIM)
clickhouse_program_install(clickhouse-ssl-shim ssl-shim)
endif()
if (ENABLE_CLICKHOUSE_SSL_HANDSHAKER)
clickhouse_program_install(clickhouse-ssl-handshaker ssl-handshaker)
endif()
if (ENABLE_CLICKHOUSE_ACVP_SERVER)
clickhouse_program_install(clickhouse-acvp-server acvp-server)
endif()

add_custom_target (clickhouse-bundle ALL DEPENDS ${CLICKHOUSE_BUNDLE})

if (USE_BINARY_HASH)
Expand Down
6 changes: 6 additions & 0 deletions programs/acvp-server/AcvpServer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
extern int acvp_modulewrapper_main(int argc, char ** argv);

int mainEntryClickHouseAcvpServer(int argc, char ** argv)
{
return acvp_modulewrapper_main(argc, argv);
}
3 changes: 3 additions & 0 deletions programs/config_tools.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
#cmakedefine01 ENABLE_CLICKHOUSE_KEEPER
#cmakedefine01 ENABLE_CLICKHOUSE_KEEPER_CLIENT
#cmakedefine01 ENABLE_CLICKHOUSE_KEEPER_CONVERTER
#cmakedefine01 ENABLE_CLICKHOUSE_SSL_SHIM
#cmakedefine01 ENABLE_CLICKHOUSE_SSL_HANDSHAKER
#cmakedefine01 ENABLE_CLICKHOUSE_ACVP_SERVER
19 changes: 19 additions & 0 deletions programs/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ int mainEntryClickHouseKeeperBench(int argc, char ** argv);
int mainEntryClickHouseKeeperDataDumper(int argc, char ** argv);
#endif

#if ENABLE_CLICKHOUSE_SSL_SHIM
int mainEntryClickHouseSslShim(int argc, char ** argv);
#endif
#if ENABLE_CLICKHOUSE_SSL_HANDSHAKER
int mainEntryClickHouseSslHandshaker(int argc, char ** argv);
#endif
#if ENABLE_CLICKHOUSE_ACVP_SERVER
int mainEntryClickHouseAcvpServer(int argc, char ** argv);
#endif

// install
int mainEntryClickHouseInstall(int argc, char ** argv);
int mainEntryClickHouseStart(int argc, char ** argv);
Expand Down Expand Up @@ -115,6 +125,15 @@ std::pair<std::string_view, MainFunc> clickhouse_applications[] =
#endif
#if USE_NURAFT
{"keeper-data-dumper", mainEntryClickHouseKeeperDataDumper},
#endif
#if ENABLE_CLICKHOUSE_SSL_SHIM
{"ssl-shim", mainEntryClickHouseSslShim},
#endif
#if ENABLE_CLICKHOUSE_SSL_HANDSHAKER
{"ssl-handshaker", mainEntryClickHouseSslHandshaker},
#endif
#if ENABLE_CLICKHOUSE_ACVP_SERVER
{"acvp-server", mainEntryClickHouseAcvpServer},
#endif
// install
{"install", mainEntryClickHouseInstall},
Expand Down
Loading
Loading