Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions contrib/openssl-cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ if(FIPS_CLICKHOUSE)
set(AWSLC_BUILD_DIR "${CMAKE_BINARY_DIR}/awslc-build")
set(AWSLC_BINARIES_DIR "${AWSLC_BUILD_DIR}/output")

# When the caller doesn't supply -DAWSLC_SRC_DIR=…, auto-set it to the
# source tree that the Docker build extracts alongside the compiled libs.
# The actual files arrive at ninja-time (the build-awslc target copies them
# out of the container), but CMake only needs the path to be DEFINED at
# configure-time so the ssl-shim/handshaker/acvp targets are created.
if(NOT DEFINED AWSLC_SRC_DIR)
set(AWSLC_SRC_DIR "${AWSLC_BUILD_DIR}/awslc-src" CACHE PATH
"Path to AWS-LC source tree (auto-populated from Docker build)")
message(STATUS "AWSLC_SRC_DIR not set; will extract source from Docker build to ${AWSLC_SRC_DIR}")
endif()

message("Will build AWS-LC FIPS 2.0.0 in FIPS mode according to security policy #4816.")
# build AWS-LC in FIPS mode accoring to the Security Policy:
# https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp4816.pdf
Expand All @@ -42,6 +53,16 @@ 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 source files needed by ssl-shim / ssl-handshaker / acvp-server.
# These targets compile AWS-LC test harness sources with the system compiler.
readonly src_dir=$OUTPUT_DIR/../awslc-src
mkdir -p $src_dir
docker cp $id:$lib_dir/ssl $src_dir/ssl
docker cp $id:$lib_dir/crypto $src_dir/crypto
docker cp $id:$lib_dir/util $src_dir/util
docker cp $id:$lib_dir/include $src_dir/include
docker cp $id:$lib_dir/third_party $src_dir/third_party 2>/dev/null || true

docker rm $id"
)

Expand Down
28 changes: 28 additions & 0 deletions programs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ else()
message(STATUS "ClickHouse keeper-client mode: OFF")
endif()

if (FIPS_CLICKHOUSE AND DEFINED AWSLC_SRC_DIR)
set(ENABLE_CLICKHOUSE_SSL_SHIM 1)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(ENABLE_CLICKHOUSE_SSL_HANDSHAKER 1)
set(ENABLE_CLICKHOUSE_ACVP_SERVER 1)
endif()
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 @@ -127,6 +135,16 @@ if (ENABLE_CLICKHOUSE_KEEPER)
add_subdirectory (keeper)
endif()

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

if (ENABLE_CLICKHOUSE_SELF_EXTRACTING AND NOT ENABLE_DUMMY_LAUNCHERS)
add_subdirectory (self-extracting)
endif ()
Expand Down Expand Up @@ -225,6 +243,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);
}
96 changes: 96 additions & 0 deletions programs/acvp-server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
if(NOT FIPS_CLICKHOUSE OR NOT DEFINED AWSLC_SRC_DIR)
return()
endif()

if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
return()
endif()

set(AWSLC_ACVP_MODULEWRAPPER_DIR "${AWSLC_SRC_DIR}/util/fipstools/acvp/modulewrapper")
set(AWSLC_LIBCRYPTO "${CMAKE_BINARY_DIR}/awslc-build/output/libcrypto.a")

set(ACVP_OBJ_DIR "${CMAKE_CURRENT_BINARY_DIR}/awslc_acvp_server_objs")

set(AWSLC_ACVP_SERVER_CXX_SRCS
${AWSLC_ACVP_MODULEWRAPPER_DIR}/main.cc
${AWSLC_ACVP_MODULEWRAPPER_DIR}/modulewrapper.cc
)

set(AWSLC_ACVP_SERVER_INCLUDE_FLAGS
-I${AWSLC_ACVP_MODULEWRAPPER_DIR}
-I${AWSLC_SRC_DIR}/include
-I${AWSLC_SRC_DIR}
)

set(AWSLC_ACVP_SERVER_OBJS)
foreach(src ${AWSLC_ACVP_SERVER_CXX_SRCS})
get_filename_component(base "${src}" NAME_WE)
get_filename_component(dir "${src}" DIRECTORY)
string(MD5 dir_hash "${dir}")
string(SUBSTRING "${dir_hash}" 0 8 dir_tag)
set(obj "${ACVP_OBJ_DIR}/${base}_${dir_tag}.o")

set(extra_defs "")
if("${base}" STREQUAL "main")
set(extra_defs -Dmain=acvp_modulewrapper_main)
endif()

add_custom_command(
OUTPUT "${obj}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${ACVP_OBJ_DIR}"
COMMAND /usr/bin/c++
-std=c++17 -fPIC -g -O2
${AWSLC_ACVP_SERVER_INCLUDE_FLAGS}
${extra_defs}
-w
-c "${src}"
-o "${obj}"
DEPENDS "${src}" build-awslc
COMMENT "Building aws-lc acvp-server object ${base}.cc (system C++ ABI)"
)
list(APPEND AWSLC_ACVP_SERVER_OBJS "${obj}")
endforeach()

set(GLIBC_COMPAT_ACVP_OBJ "${ACVP_OBJ_DIR}/glibc_compat.o")
add_custom_command(
OUTPUT "${GLIBC_COMPAT_ACVP_OBJ}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${ACVP_OBJ_DIR}"
COMMAND /usr/bin/cc -fPIC -O2 -w
-c "${CMAKE_CURRENT_SOURCE_DIR}/../ssl-common/glibc_compat.c"
-o "${GLIBC_COMPAT_ACVP_OBJ}"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/../ssl-common/glibc_compat.c"
COMMENT "Building glibc C23 compat shim (acvp-server)"
)
list(APPEND AWSLC_ACVP_SERVER_OBJS "${GLIBC_COMPAT_ACVP_OBJ}")

set(AWSLC_ACVP_SERVER_LIB "${ACVP_OBJ_DIR}/libawslc_acvp_server.a")
add_custom_command(
OUTPUT "${AWSLC_ACVP_SERVER_LIB}"
COMMAND ${CMAKE_AR} rcs "${AWSLC_ACVP_SERVER_LIB}" ${AWSLC_ACVP_SERVER_OBJS}
DEPENDS ${AWSLC_ACVP_SERVER_OBJS}
COMMENT "Archiving libawslc_acvp_server.a"
)
add_custom_target(awslc_acvp_server_lib DEPENDS "${AWSLC_ACVP_SERVER_LIB}")

set(CLICKHOUSE_ACVP_SERVER_SOURCES AcvpServer.cpp)
find_file(LIBSTDCXX_STATIC_ACVP libstdc++.a
PATHS /usr/lib/gcc/x86_64-linux-gnu
PATH_SUFFIXES 13 12 11
NO_DEFAULT_PATH
)
if(NOT LIBSTDCXX_STATIC_ACVP)
message(FATAL_ERROR "Could not find static libstdc++.a needed for acvp-server")
endif()

set(CLICKHOUSE_ACVP_SERVER_LINK
PRIVATE
"${AWSLC_ACVP_SERVER_LIB}"
"${AWSLC_LIBCRYPTO}"
"${LIBSTDCXX_STATIC_ACVP}"
)
set(CLICKHOUSE_ACVP_SERVER_INCLUDE PRIVATE ${AWSLC_SRC_DIR}/include)

clickhouse_program_add(acvp-server)
add_dependencies(clickhouse-acvp-server-lib awslc_acvp_server_lib build-awslc)
target_compile_options(clickhouse-acvp-server-lib PRIVATE -Wno-everything)
target_link_options(clickhouse-acvp-server-lib INTERFACE "LINKER:--allow-multiple-definition")
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
157 changes: 157 additions & 0 deletions programs/ssl-common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Running SSL and ACVP Tests Manually for ClickHouse FIPS Build

This guide explains how to run the AWS-LC SSL conformance tests and ACVP
cryptographic algorithm validation tests against the ClickHouse FIPS binary.

## Prerequisites

- ClickHouse built with `-DFIPS_CLICKHOUSE=1` and `-DAWSLC_SRC_DIR=<path>`
(or the auto-populated source from the Docker build)
- The resulting binary must contain the `ssl-shim`, `ssl-handshaker`, and
`acvp-server` modes (verify with `./clickhouse ssl-shim --help`)
- **Go >= 1.13** (the AWS-LC test harness is written in Go)
- A checkout of the AWS-LC source matching the FIPS build version
(`AWS-LC-FIPS-2.0.0`), which is the same tree referenced by `AWSLC_SRC_DIR`

Throughout this document, the following paths are used as examples:

| Variable | Example Path |
|---|---|
| `CLICKHOUSE_BUILD` | `/path/to/ClickHouse/build` |
| `AWSLC_SRC` | `/path/to/aws-lc` (the AWS-LC source root) |

## SSL Tests (8,037 tests)

The SSL test suite exercises the full TLS stack: handshake flows, cipher
negotiation, session resumption, certificate handling, QUIC transport, and
more. It uses a Go test runner that drives the ClickHouse `ssl-shim` and
`ssl-handshaker` binaries.

### Create symlinks

The Go test runner invokes `bssl_shim` and `handshaker` by path. Create
symlinks from the ClickHouse binary:

```bash
ln -sf "$CLICKHOUSE_BUILD/programs/clickhouse" "$CLICKHOUSE_BUILD/programs/clickhouse-ssl-shim"
ln -sf "$CLICKHOUSE_BUILD/programs/clickhouse" "$CLICKHOUSE_BUILD/programs/clickhouse-ssl-handshaker"
```

### Run the tests

```bash
cd "$AWSLC_SRC/ssl/test/runner"

go test -v . \
-shim-path "$CLICKHOUSE_BUILD/programs/clickhouse-ssl-shim" \
-handshaker-path "$CLICKHOUSE_BUILD/programs/clickhouse-ssl-handshaker" \
-num-workers 16
```

`-num-workers` defaults to the number of CPU cores. Adjust as needed.

### Expected results

All 8,037 tests should pass. A passing run ends with output similar to:

```
PASS
ok boringssl.googlesource.com/boringssl/ssl/test/runner 142.538s
```

If any tests fail, the runner prints the failing test name and a diff of
the expected vs. actual TLS behavior.

## ACVP Tests (31 algorithm suites)

The ACVP (Automated Cryptographic Validation Protocol) tests validate that
the FIPS cryptographic module produces correct outputs for known-answer test
vectors. AWS-LC bundles 31 algorithm suites with pre-computed expected
results.

### Build the test tools

```bash
cd "$AWSLC_SRC/util/fipstools/acvp/acvptool"

# Build acvptool (the ACVP JSON ↔ modulewrapper translator)
go build -o /tmp/acvptool .

# Build testmodulewrapper (needed by 2 of the 31 test suites)
cd "$AWSLC_SRC/util/fipstools/acvp/acvptool/testmodulewrapper"
go build -o /tmp/testmodulewrapper .
```

### Create the acvp-server symlink

```bash
ln -sf "$CLICKHOUSE_BUILD/programs/clickhouse" "$CLICKHOUSE_BUILD/programs/clickhouse-acvp-server"
```

### Run the tests

```bash
cd "$AWSLC_SRC/util/fipstools/acvp/acvptool/test"

go run check_expected.go \
-tool /tmp/acvptool \
-module-wrappers "modulewrapper:$CLICKHOUSE_BUILD/programs/clickhouse-acvp-server,testmodulewrapper:/tmp/testmodulewrapper" \
-tests tests.json
```

### Expected results

All 31 test suites should pass (some have no expected output and only verify
that the module does not crash):

```
All tests passed
```

The 31 validated algorithm suites are:

| Category | Algorithms |
|---|---|
| AES | CBC, CCM, CTR, ECB, GCM, GMAC, KW, KWP, XTS, CBC-CS3 (via testmodulewrapper) |
| DRBG | ctrDRBG, hmacDRBG (via testmodulewrapper) |
| ECDSA | KeyGen, SigGen, SigVer |
| HMAC | SHA-1, SHA2-224, SHA2-256, SHA2-384, SHA2-512, SHA2-512/256 |
| KAS | ECC-SSC, FFC-SSC |
| KDF | SP800-108, kdf-components (TLS, SSH), HKDF |
| RSA | KeyGen, SigGen, SigVer |
| TLS | TLS-1.2-KDF |
| Other | PBKDF, AES-GCM-internal-IV |

## Troubleshooting

### `clickhouse ssl-shim` says "unknown mode"

The binary was built without the FIPS test targets. Re-run CMake with:

```bash
cmake .. -DFIPS_CLICKHOUSE=1 -DAWSLC_SRC_DIR=/path/to/aws-lc
```

and rebuild. If `AWSLC_SRC_DIR` was auto-populated from the Docker build,
ensure the Docker build completed successfully (check that
`build/awslc-build/awslc-src/ssl/test/bssl_shim.cc` exists).

### Go test runner shows fewer than 8,037 tests

Make sure you are running from the `ssl/test/runner/` directory inside the
AWS-LC source tree, not from a different BoringSSL checkout.

### ACVP `check_expected.go` fails with "wrapper returned error"

Verify that `clickhouse-acvp-server` symlink exists and points to the
ClickHouse binary. Also verify it is executable:

```bash
"$CLICKHOUSE_BUILD/programs/clickhouse-acvp-server" --help
```

### Permission denied on Docker socket during build

The AWS-LC FIPS libraries are built inside a Docker container per the FIPS
140-3 security policy. Ensure the build user has access to the Docker
daemon (is in the `docker` group or has rootless Docker configured).
Loading
Loading