Skip to content

Commit 87c961e

Browse files
authored
Merge pull request #1560 from Altinity/features/25.3/fips-ch-binary-extended-testing
SSL/ACVP Test Integration for FIPS - second try
2 parents d1e8b14 + 9c61bc5 commit 87c961e

13 files changed

Lines changed: 725 additions & 1 deletion

File tree

contrib/openssl-cmake/CMakeLists.txt

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ docker cp $id:$lib_dir/build/ssl/libssl.a $OUTPUT_DIR
4242
docker cp $id:$lib_dir/build/crypto/libcrypto.a $OUTPUT_DIR
4343
docker cp $id:$lib_dir/include $OUTPUT_DIR
4444
45+
# Extract pre-built test harness libraries (symbol-localized, with libstdc++ baked in)
46+
docker cp $id:/harness-output/libawslc_shim.a $OUTPUT_DIR
47+
docker cp $id:/harness-output/libawslc_handshaker.a $OUTPUT_DIR
48+
docker cp $id:/harness-output/libawslc_acvp_server.a $OUTPUT_DIR
49+
4550
docker rm $id"
4651
)
4752

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

7176
add_custom_target(build-awslc
7277
COMMENT "Build AWS-LC in FIPS mode with docker"
73-
DEPENDS ${AWSLC_BINARIES_DIR}/libssl.a ${AWSLC_BINARIES_DIR}/libcrypto.a
78+
DEPENDS
79+
${AWSLC_BINARIES_DIR}/libssl.a
80+
${AWSLC_BINARIES_DIR}/libcrypto.a
81+
${AWSLC_BINARIES_DIR}/libawslc_shim.a
82+
${AWSLC_BINARIES_DIR}/libawslc_handshaker.a
83+
${AWSLC_BINARIES_DIR}/libawslc_acvp_server.a
7484
)
7585

7686
if(ARCH_AARCH64)
@@ -83,7 +93,20 @@ add_custom_command(
8393
OUTPUT
8494
"${AWSLC_BUILD_DIR}/output/libssl.a"
8595
"${AWSLC_BUILD_DIR}/output/libcrypto.a"
96+
"${AWSLC_BUILD_DIR}/output/libawslc_shim.a"
97+
"${AWSLC_BUILD_DIR}/output/libawslc_handshaker.a"
98+
"${AWSLC_BUILD_DIR}/output/libawslc_acvp_server.a"
8699
COMMENT "Building AWS-LC in FIPS mode using docker"
100+
# Copy test harness build inputs into the Docker context directory
101+
COMMAND ${CMAKE_COMMAND} -E copy
102+
${ClickHouse_SOURCE_DIR}/programs/ssl-common/posix_spawn_2.c
103+
${AWSLC_BUILD_DIR}/posix_spawn_2.c
104+
COMMAND ${CMAKE_COMMAND} -E copy
105+
${ClickHouse_SOURCE_DIR}/programs/ssl-common/glibc_compat.c
106+
${AWSLC_BUILD_DIR}/glibc_compat.c
107+
COMMAND ${CMAKE_COMMAND} -E copy
108+
${CMAKE_CURRENT_SOURCE_DIR}/build_test_harness.sh
109+
${AWSLC_BUILD_DIR}/build_test_harness.sh
87110
COMMAND bash -c "chmod +x ${AWSLC_BUILD_DIR}/build_awclc_fips.sh"
88111
COMMAND bash -c "${AWSLC_BUILD_DIR}/build_awclc_fips.sh ${AWSLC_BINARIES_DIR} ${DOCKERFILE_PATH}"
89112
WORKING_DIRECTORY ${AWSLC_BUILD_DIR}
@@ -92,6 +115,9 @@ add_custom_command(
92115
${AWSLC_BUILD_DIR}/build_awclc_fips.sh
93116
${AWSLC_BUILD_DIR}/check_version.c
94117
${DOCKERFILE_PATH}
118+
${ClickHouse_SOURCE_DIR}/programs/ssl-common/posix_spawn_2.c
119+
${ClickHouse_SOURCE_DIR}/programs/ssl-common/glibc_compat.c
120+
${CMAKE_CURRENT_SOURCE_DIR}/build_test_harness.sh
95121
)
96122

97123
add_library(crypto UNKNOWN IMPORTED GLOBAL)
@@ -130,6 +156,45 @@ target_compile_options(ssl INTERFACE
130156
target_compile_options(global-group INTERFACE "-Wno-deprecated-declarations")
131157
target_compile_options(global-group INTERFACE "-Wno-poison-system-directories")
132158

159+
# ── Test harness IMPORTED libraries ──────────────────────────────────────────
160+
# These archives are built inside Docker (build_test_harness.sh), partially
161+
# linked with libstdc++ via `ld -r`, and symbol-localized so only the entry
162+
# point is globally visible. No --allow-multiple-definition needed.
163+
164+
add_library(awslc_shim STATIC IMPORTED GLOBAL)
165+
add_dependencies(awslc_shim build-awslc)
166+
set_target_properties(awslc_shim PROPERTIES
167+
IMPORTED_LOCATION "${AWSLC_BINARIES_DIR}/libawslc_shim.a")
168+
169+
add_library(awslc_handshaker STATIC IMPORTED GLOBAL)
170+
add_dependencies(awslc_handshaker build-awslc)
171+
set_target_properties(awslc_handshaker PROPERTIES
172+
IMPORTED_LOCATION "${AWSLC_BINARIES_DIR}/libawslc_handshaker.a")
173+
174+
add_library(awslc_acvp_server STATIC IMPORTED GLOBAL)
175+
add_dependencies(awslc_acvp_server build-awslc)
176+
set_target_properties(awslc_acvp_server PROPERTIES
177+
IMPORTED_LOCATION "${AWSLC_BINARIES_DIR}/libawslc_acvp_server.a")
178+
179+
# ── Test harness program libraries ───────────────────────────────────────────
180+
# Linked into the main clickhouse binary via clickhouse_program_install()
181+
# in programs/CMakeLists.txt. The entry-point .cpp files stay in programs/.
182+
183+
add_library(clickhouse-ssl-shim-lib
184+
${ClickHouse_SOURCE_DIR}/programs/ssl-shim/SslShim.cpp)
185+
target_link_libraries(clickhouse-ssl-shim-lib PRIVATE awslc_shim ssl crypto)
186+
add_dependencies(clickhouse-ssl-shim-lib build-awslc)
187+
188+
add_library(clickhouse-ssl-handshaker-lib
189+
${ClickHouse_SOURCE_DIR}/programs/ssl-handshaker/SslHandshaker.cpp)
190+
target_link_libraries(clickhouse-ssl-handshaker-lib PRIVATE awslc_handshaker ssl crypto)
191+
add_dependencies(clickhouse-ssl-handshaker-lib build-awslc)
192+
193+
add_library(clickhouse-acvp-server-lib
194+
${ClickHouse_SOURCE_DIR}/programs/acvp-server/AcvpServer.cpp)
195+
target_link_libraries(clickhouse-acvp-server-lib PRIVATE awslc_acvp_server crypto)
196+
add_dependencies(clickhouse-acvp-server-lib build-awslc)
197+
133198
else() # FIPS_CLICKHOUSE
134199

135200

contrib/openssl-cmake/Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@ RUN test $(/aws-lc-AWS-LC-FIPS-2.0.0/build/tool/bssl isfips) = 1
3030

3131
# execute all test
3232
RUN find /aws-lc-AWS-LC-FIPS-2.0.0/build -iname '*test*' -type f -executable -print -exec {} \;
33+
34+
# Build test harness libraries for ClickHouse FIPS testing integration
35+
COPY posix_spawn_2.c glibc_compat.c /tmp/
36+
COPY build_test_harness.sh /tmp/
37+
RUN chmod +x /tmp/build_test_harness.sh && \
38+
/tmp/build_test_harness.sh /aws-lc-AWS-LC-FIPS-2.0.0 /harness-output

contrib/openssl-cmake/Dockerfile.aarch64

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@ RUN test $(/aws-lc-AWS-LC-FIPS-2.0.0/build/tool/bssl isfips) = 1
3030

3131
# execute all test
3232
RUN find /aws-lc-AWS-LC-FIPS-2.0.0/build -iname '*test*' -type f -executable -print -exec {} \;
33+
34+
# Build test harness libraries for ClickHouse FIPS testing integration
35+
COPY posix_spawn_2.c glibc_compat.c /tmp/
36+
COPY build_test_harness.sh /tmp/
37+
RUN chmod +x /tmp/build_test_harness.sh && \
38+
/tmp/build_test_harness.sh /aws-lc-AWS-LC-FIPS-2.0.0 /harness-output
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/bin/bash
2+
# Build test harness static libraries for ClickHouse FIPS testing integration.
3+
#
4+
# Each library is partially linked with libstdc++ via `ld -r` and then all
5+
# symbols are prefixed with __awslc_ using `objcopy --prefix-symbols`.
6+
# Undefined symbols (libssl/libcrypto/libc refs) and the entry point are
7+
# restored to their original names via `--redefine-syms`.
8+
#
9+
# This prevents libstdc++ symbols from colliding with ClickHouse's libc++
10+
# at final link time, while keeping COMDAT groups intact (localizing COMDAT
11+
# key symbols would cause lld to discard their sections).
12+
#
13+
# Usage: build_test_harness.sh <awslc-src-dir> <output-dir>
14+
set -ex
15+
16+
SRC=${1:?usage: build_test_harness.sh <awslc-src-dir> <output-dir>}
17+
OUTDIR=${2:?usage: build_test_harness.sh <awslc-src-dir> <output-dir>}
18+
mkdir -p "$OUTDIR"
19+
20+
CXXFLAGS="-std=c++17 -fPIC -g -O2 -fno-exceptions -w"
21+
CFLAGS="-fPIC -O2 -w"
22+
INC="-I$SRC/include -I$SRC -I$SRC/ssl/test"
23+
STDCXX=$(c++ -print-file-name=libstdc++.a)
24+
PREFIX="__awslc_"
25+
26+
# build_target <name> <entry_grep> <obj_dir>
27+
# Partial-links .o files in <obj_dir> with libstdc++, prefixes all symbols,
28+
# then restores undefined refs and entry point to original names.
29+
build_target() {
30+
local name=$1 entry_grep=$2 obj_dir=$3
31+
ld -r -o "$obj_dir/combined.o" "$obj_dir"/*.o "$STDCXX"
32+
33+
# Collect undefined symbols — these reference external libraries
34+
# (libssl, libcrypto, libc, pthreads) and must keep their original names.
35+
nm -u "$obj_dir/combined.o" | awk 'NF>=2{print $NF}' | sort -u > "$obj_dir/undef.txt"
36+
37+
# Find entry point symbol
38+
nm "$obj_dir/combined.o" | awk "/T.*${entry_grep}/{print \$3}" > "$obj_dir/entry.txt"
39+
40+
# Build redefine map: after --prefix-symbols adds the prefix,
41+
# restore undefined symbols and entry point to original names.
42+
awk -v p="$PREFIX" '{print p $0 " " $0}' "$obj_dir/undef.txt" > "$obj_dir/redefine.txt"
43+
awk -v p="$PREFIX" '{print p $0 " " $0}' "$obj_dir/entry.txt" >> "$obj_dir/redefine.txt"
44+
45+
# Two passes: objcopy applies --redefine-syms BEFORE --prefix-symbols
46+
# in a single invocation, so we must split them.
47+
# Pass 1: prefix every symbol.
48+
objcopy --prefix-symbols="$PREFIX" "$obj_dir/combined.o"
49+
# Pass 2: restore undefined refs + entry point to original names,
50+
# and weaken all defined symbols so duplicates across archives
51+
# (same libstdc++ members pulled into shim, handshaker, acvp) don't clash.
52+
objcopy --redefine-syms="$obj_dir/redefine.txt" --weaken "$obj_dir/combined.o"
53+
54+
ar rcs "$OUTDIR/lib${name}.a" "$obj_dir/combined.o"
55+
rm -rf "$obj_dir"
56+
}
57+
58+
# --- ssl-shim ---
59+
OBJ=$(mktemp -d)
60+
for f in async_bio bssl_shim handshake_util mock_quic_transport \
61+
packeted_bio settings_writer ssl_transfer test_config test_state; do
62+
EXTRA="-Dposix_spawn=__ssl_posix_spawn"
63+
[ "$f" = "bssl_shim" ] && EXTRA="$EXTRA -Dmain=bssl_shim_main"
64+
c++ $CXXFLAGS $INC $EXTRA -c "$SRC/ssl/test/$f.cc" -o "$OBJ/$f.o"
65+
done
66+
c++ $CXXFLAGS $INC -Dposix_spawn=__ssl_posix_spawn \
67+
-c "$SRC/crypto/test/test_util.cc" -o "$OBJ/test_util.o"
68+
cc $CFLAGS -c /tmp/posix_spawn_2.c -o "$OBJ/posix_spawn_2.o"
69+
cc $CFLAGS -c /tmp/glibc_compat.c -o "$OBJ/glibc_compat.o"
70+
build_target awslc_shim bssl_shim_main "$OBJ"
71+
72+
# --- ssl-handshaker ---
73+
OBJ=$(mktemp -d)
74+
for f in async_bio handshake_util handshaker mock_quic_transport \
75+
packeted_bio settings_writer test_config test_state; do
76+
EXTRA="-Dposix_spawn=__ssl_posix_spawn"
77+
[ "$f" = "handshaker" ] && EXTRA="$EXTRA -Dmain=handshaker_main"
78+
c++ $CXXFLAGS $INC $EXTRA -c "$SRC/ssl/test/$f.cc" -o "$OBJ/$f.o"
79+
done
80+
c++ $CXXFLAGS $INC -Dposix_spawn=__ssl_posix_spawn \
81+
-c "$SRC/crypto/test/test_util.cc" -o "$OBJ/test_util.o"
82+
cc $CFLAGS -c /tmp/posix_spawn_2.c -o "$OBJ/posix_spawn_2.o"
83+
cc $CFLAGS -c /tmp/glibc_compat.c -o "$OBJ/glibc_compat.o"
84+
build_target awslc_handshaker handshaker_main "$OBJ"
85+
86+
# --- acvp-server ---
87+
OBJ=$(mktemp -d)
88+
ACVP_DIR="$SRC/util/fipstools/acvp/modulewrapper"
89+
c++ $CXXFLAGS -I"$ACVP_DIR" -I"$SRC/include" -I"$SRC" \
90+
-Dmain=acvp_modulewrapper_main \
91+
-c "$ACVP_DIR/main.cc" -o "$OBJ/main.o"
92+
c++ $CXXFLAGS -I"$ACVP_DIR" -I"$SRC/include" -I"$SRC" \
93+
-c "$ACVP_DIR/modulewrapper.cc" -o "$OBJ/modulewrapper.o"
94+
cc $CFLAGS -c /tmp/glibc_compat.c -o "$OBJ/glibc_compat.o"
95+
build_target awslc_acvp_server acvp_modulewrapper_main "$OBJ"

programs/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ else()
6262
message(STATUS "ClickHouse keeper-client mode: OFF")
6363
endif()
6464

65+
if (FIPS_CLICKHOUSE AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
66+
set(ENABLE_CLICKHOUSE_SSL_SHIM 1)
67+
set(ENABLE_CLICKHOUSE_SSL_HANDSHAKER 1)
68+
set(ENABLE_CLICKHOUSE_ACVP_SERVER 1)
69+
endif()
70+
6571
configure_file (config_tools.h.in ${CONFIG_INCLUDE_PATH}/config_tools.h)
6672

6773
macro(clickhouse_target_link_split_lib target name)
@@ -225,6 +231,16 @@ if (ENABLE_CLICKHOUSE_KEEPER_CLIENT)
225231
list(APPEND CLICKHOUSE_BUNDLE clickhouse-keeper-client)
226232
endif ()
227233

234+
if (ENABLE_CLICKHOUSE_SSL_SHIM)
235+
clickhouse_program_install(clickhouse-ssl-shim ssl-shim)
236+
endif()
237+
if (ENABLE_CLICKHOUSE_SSL_HANDSHAKER)
238+
clickhouse_program_install(clickhouse-ssl-handshaker ssl-handshaker)
239+
endif()
240+
if (ENABLE_CLICKHOUSE_ACVP_SERVER)
241+
clickhouse_program_install(clickhouse-acvp-server acvp-server)
242+
endif()
243+
228244
add_custom_target (clickhouse-bundle ALL DEPENDS ${CLICKHOUSE_BUNDLE})
229245

230246
if (USE_BINARY_HASH)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extern int acvp_modulewrapper_main(int argc, char ** argv);
2+
3+
int mainEntryClickHouseAcvpServer(int argc, char ** argv)
4+
{
5+
return acvp_modulewrapper_main(argc, argv);
6+
}

programs/config_tools.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
#cmakedefine01 ENABLE_CLICKHOUSE_KEEPER
66
#cmakedefine01 ENABLE_CLICKHOUSE_KEEPER_CLIENT
77
#cmakedefine01 ENABLE_CLICKHOUSE_KEEPER_CONVERTER
8+
#cmakedefine01 ENABLE_CLICKHOUSE_SSL_SHIM
9+
#cmakedefine01 ENABLE_CLICKHOUSE_SSL_HANDSHAKER
10+
#cmakedefine01 ENABLE_CLICKHOUSE_ACVP_SERVER

programs/main.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ int mainEntryClickHouseKeeperBench(int argc, char ** argv);
6464
int mainEntryClickHouseKeeperDataDumper(int argc, char ** argv);
6565
#endif
6666

67+
#if ENABLE_CLICKHOUSE_SSL_SHIM
68+
int mainEntryClickHouseSslShim(int argc, char ** argv);
69+
#endif
70+
#if ENABLE_CLICKHOUSE_SSL_HANDSHAKER
71+
int mainEntryClickHouseSslHandshaker(int argc, char ** argv);
72+
#endif
73+
#if ENABLE_CLICKHOUSE_ACVP_SERVER
74+
int mainEntryClickHouseAcvpServer(int argc, char ** argv);
75+
#endif
76+
6777
// install
6878
int mainEntryClickHouseInstall(int argc, char ** argv);
6979
int mainEntryClickHouseStart(int argc, char ** argv);
@@ -115,6 +125,15 @@ std::pair<std::string_view, MainFunc> clickhouse_applications[] =
115125
#endif
116126
#if USE_NURAFT
117127
{"keeper-data-dumper", mainEntryClickHouseKeeperDataDumper},
128+
#endif
129+
#if ENABLE_CLICKHOUSE_SSL_SHIM
130+
{"ssl-shim", mainEntryClickHouseSslShim},
131+
#endif
132+
#if ENABLE_CLICKHOUSE_SSL_HANDSHAKER
133+
{"ssl-handshaker", mainEntryClickHouseSslHandshaker},
134+
#endif
135+
#if ENABLE_CLICKHOUSE_ACVP_SERVER
136+
{"acvp-server", mainEntryClickHouseAcvpServer},
118137
#endif
119138
// install
120139
{"install", mainEntryClickHouseInstall},

0 commit comments

Comments
 (0)