Skip to content

Commit 93ef530

Browse files
committed
Also support Clang compiler
1 parent 77103f0 commit 93ef530

File tree

9 files changed

+89
-50
lines changed

9 files changed

+89
-50
lines changed

.github/workflows/windows-alt.yml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ permissions:
1313
contents: read
1414

1515
jobs:
16+
# MinGW GCC does not support FIPS because it lacks support for MSVC-specific
17+
# pragmas (code_seg, data_seg, etc.) required for FIPS section placement.
1618
mingw:
1719
if: github.repository_owner == 'aws'
1820
runs-on: windows-latest
@@ -52,6 +54,13 @@ jobs:
5254
clang:
5355
if: github.repository_owner == 'aws'
5456
runs-on: windows-latest
57+
strategy:
58+
fail-fast: false
59+
matrix:
60+
fips:
61+
- 0
62+
- 1
63+
name: clang${{ matrix.fips == 1 && ' FIPS' || '' }}
5564
steps:
5665
- name: Install NASM
5766
uses: ilammy/setup-nasm@v1.5.1
@@ -73,6 +82,8 @@ jobs:
7382
CMAKE_SYSTEM_NAME=Windows \
7483
CMAKE_SYSTEM_PROCESSOR=x86_64 \
7584
CMAKE_BUILD_TYPE=Release \
85+
BUILD_SHARED_LIBS=${{ matrix.fips }} \
86+
FIPS=${{ matrix.fips }} \
7687
- name: Build Project
7788
run: cmake --build ./build --target all
7889
- name: Run tests
@@ -85,7 +96,14 @@ jobs:
8596
target:
8697
- x64
8798
- x64_arm64
99+
fips:
100+
- 0
101+
- 1
102+
exclude:
103+
- target: x64_arm64
104+
fips: 1
88105
runs-on: windows-latest
106+
name: clang-cl-msbuild ${{ matrix.target }}${{ matrix.fips == 1 && ' FIPS' || '' }}
89107
env:
90108
CMAKE_GENERATOR: "Visual Studio 17 2022"
91109
CMAKE_GENERATOR_TOOLSET: "ClangCL,host=x64"
@@ -104,6 +122,8 @@ jobs:
104122
with:
105123
options: |
106124
CMAKE_BUILD_TYPE=Release \
125+
BUILD_SHARED_LIBS=${{ matrix.fips }} \
126+
FIPS=${{ matrix.fips }} \
107127
- if: ${{ matrix.target == 'x64_arm64' }}
108128
name: Setup CMake
109129
uses: threeal/cmake-action@v1.3.0
@@ -113,6 +133,9 @@ jobs:
113133
CMAKE_SYSTEM_NAME=Windows \
114134
CMAKE_SYSTEM_PROCESSOR=ARM64 \
115135
CMAKE_BUILD_TYPE=Release \
136+
- if: ${{ matrix.fips == 1 }}
137+
name: Build FIPS module
138+
run: cmake --build ./build --target fips_empty_main
116139
- name: Build Project
117140
run: cmake --build ./build --target all_tests
118141
- if: ${{ matrix.target == 'x64' }}
@@ -126,7 +149,14 @@ jobs:
126149
target:
127150
- x64
128151
- x64_arm64
152+
fips:
153+
- 0
154+
- 1
155+
exclude:
156+
- target: x64_arm64
157+
fips: 1
129158
runs-on: windows-latest
159+
name: clang-cl-ninja ${{ matrix.target }}${{ matrix.fips == 1 && ' FIPS' || '' }}
130160
steps:
131161
- if: ${{ matrix.target == 'x64' }}
132162
name: Install NASM
@@ -147,6 +177,8 @@ jobs:
147177
cxx-compiler: clang-cl
148178
options: |
149179
CMAKE_BUILD_TYPE=Release \
180+
BUILD_SHARED_LIBS=${{ matrix.fips }} \
181+
FIPS=${{ matrix.fips }} \
150182
- if: ${{ matrix.target == 'x64_arm64' }}
151183
name: Setup CMake
152184
uses: threeal/cmake-action@v1.3.0
@@ -193,7 +225,6 @@ jobs:
193225
run:
194226
./tests/ci/run_cross_mingw_tests.sh x86_64 w64-mingw32 "-DCMAKE_BUILD_TYPE=Release"
195227
msys2:
196-
name: msys2 ${{ matrix.sys }} - ${{ matrix.generator }}
197228
if: github.repository_owner == 'aws'
198229
runs-on: windows-latest
199230
strategy:
@@ -207,6 +238,15 @@ jobs:
207238
- 'Ninja'
208239
- 'MinGW Makefiles'
209240
- 'MSYS Makefiles'
241+
fips:
242+
- 0
243+
# FIPS is excluded for all msys2 configurations. The MinGW toolchain
244+
# (used by all msys2 environments including clang64) does not support
245+
# PE grouped sections ($a/$b/$z ordering), __declspec(allocate()), or
246+
# COFF .lib archives — all of which are required for FIPS section
247+
# placement. FIPS on Windows requires the MSVC toolchain (link.exe or
248+
# lld-link in MSVC mode).
249+
name: msys2 ${{ matrix.sys }} - ${{ matrix.generator }}${{ matrix.fips == 1 && ' FIPS' || '' }}
210250
steps:
211251
- name: Install MSYS2
212252
uses: msys2/setup-msys2@v2

crypto/CMakeLists.txt

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -628,15 +628,15 @@ endfunction()
628628
if(FIPS_SHARED)
629629
# Rewrite libcrypto.so, libcrypto.dylib, or crypto.dll to inject the correct module
630630
# hash value. For now we support the FIPS build only on Linux, macOS, iOS, and Windows.
631-
if(MSVC AND ARCH STREQUAL "aarch64")
632-
# On ARM64 Windows, ASLR is mandatory and cannot be disabled. The linker
633-
# resolves ADRP immediates differently when building two separate DLLs
634-
# (precrypto.dll vs crypto.dll), even when the FIPS module code comes from
635-
# the same bcm.lib. This makes the two-DLL capture_hash approach produce a
636-
# hash mismatch. Instead we use a single-DLL approach: build crypto.dll
637-
# once with a placeholder hash, run fips_empty_main.exe (which triggers the
638-
# integrity check, computes the real hash, and prints it), then binary-patch
639-
# the placeholder in crypto.dll with the captured hash.
631+
if(WIN32)
632+
# On Windows we use a single-DLL approach: build crypto.dll once with a
633+
# placeholder hash, run fips_empty_main.exe (which triggers the integrity
634+
# check, computes the real hash, and prints it), then binary-patch the
635+
# placeholder in crypto.dll with the captured hash.
636+
#
637+
# This avoids building two separate DLLs (precrypto.dll vs crypto.dll)
638+
# whose linker output might differ — as happens on ARM64 (mandatory ASLR
639+
# causes ADRP immediate differences) and with Clang's lld-link.
640640
build_libcrypto(NAME crypto MODULE_SOURCE $<TARGET_OBJECTS:fipsmodule> SET_OUTPUT_NAME)
641641

642642
add_executable(fips_empty_main fipsmodule/fips_empty_main.c)
@@ -651,34 +651,6 @@ if(FIPS_SHARED)
651651
-patch-dll $<TARGET_FILE:crypto>
652652
WORKING_DIRECTORY ${AWSLC_SOURCE_DIR}
653653
)
654-
elseif(MSVC)
655-
# On x64 Windows we use capture_hash.go to capture the computed integrity
656-
# value that the module prints on its first (failing) run, then embed that
657-
# value in generated_fips_shared_support.c for the final crypto.dll.
658-
# See FIPS.md for a full explanation of the process.
659-
build_libcrypto(NAME precrypto MODULE_SOURCE $<TARGET_OBJECTS:fipsmodule>)
660-
add_executable(fips_empty_main fipsmodule/fips_empty_main.c)
661-
target_link_libraries(fips_empty_main PUBLIC precrypto)
662-
target_add_awslc_include_paths(TARGET fips_empty_main SCOPE PRIVATE)
663-
add_custom_command(OUTPUT generated_fips_shared_support.c
664-
COMMAND ${GO_EXECUTABLE} run
665-
${AWSLC_SOURCE_DIR}/util/fipstools/capture_hash/capture_hash.go
666-
-in-executable $<TARGET_FILE:fips_empty_main> > ${CMAKE_CURRENT_BINARY_DIR}/generated_fips_shared_support.c
667-
WORKING_DIRECTORY ${AWSLC_SOURCE_DIR}
668-
DEPENDS fips_empty_main ${AWSLC_SOURCE_DIR}/util/fipstools/capture_hash/capture_hash.go
669-
)
670-
add_library(
671-
generated_fipsmodule
672-
673-
OBJECT
674-
675-
generated_fips_shared_support.c
676-
${AWSLC_SOURCE_DIR}/crypto/fipsmodule/cpucap/cpucap.c
677-
)
678-
target_compile_definitions(generated_fipsmodule PRIVATE BORINGSSL_IMPLEMENTATION S2N_BN_HIDE_SYMBOLS)
679-
target_add_awslc_include_paths(TARGET generated_fipsmodule SCOPE PRIVATE)
680-
681-
build_libcrypto(NAME crypto MODULE_SOURCE $<TARGET_OBJECTS:generated_fipsmodule> SET_OUTPUT_NAME)
682654
else()
683655
# On Apple and Linux platforms inject_hash.go can parse libcrypto and inject
684656
# the hash directly into the final library.

crypto/fipsmodule/CMakeLists.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,33 @@ elseif(FIPS_SHARED)
634634
DEPENDS fips_msvc_start.obj fips_msvc_end.obj bcm_library
635635
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
636636
)
637+
elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang")
638+
# Windows with Clang (not clang-cl): use llvm-lib to combine object files
639+
# into a static library. Similar to the MSVC case, we use start/end markers
640+
# to control symbol placement in the FIPS grouped sections.
641+
set(BCM_NAME bcm.lib)
642+
get_filename_component(COMPILER_DIR "${CMAKE_C_COMPILER}" DIRECTORY)
643+
find_program(LIB_TOOL "llvm-lib" "llvm-lib.exe" HINTS "${COMPILER_DIR}" REQUIRED)
644+
645+
add_custom_command(
646+
OUTPUT fips_windows_start.obj
647+
COMMAND ${CMAKE_C_COMPILER} -c -DAWSLC_FIPS_SHARED_START -o fips_windows_start.obj ${CMAKE_CURRENT_SOURCE_DIR}/fips_shared_library_marker.c
648+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fips_shared_library_marker.c
649+
)
650+
add_custom_command(
651+
OUTPUT fips_windows_end.obj
652+
COMMAND ${CMAKE_C_COMPILER} -c -DAWSLC_FIPS_SHARED_END -o fips_windows_end.obj ${CMAKE_CURRENT_SOURCE_DIR}/fips_shared_library_marker.c
653+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fips_shared_library_marker.c
654+
)
655+
656+
add_custom_command(
657+
OUTPUT ${BCM_NAME}
658+
COMMAND ${LIB_TOOL} /nologo fips_windows_start.obj "\"$<JOIN:$<TARGET_OBJECTS:bcm_library>,\" \">\"" fips_windows_end.obj /OUT:${BCM_NAME}
659+
DEPENDS bcm_library fips_windows_start.obj fips_windows_end.obj
660+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
661+
)
637662
else()
663+
# Linux/Unix: use ld -r with a linker script to create a relocatable object file.
638664
set(BCM_NAME bcm.o)
639665
# fips_shared.lds does not have 'clang' prefix because we want to keep merging any changes from upstream.
640666
set(FIPS_CUSTOM_LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/fips_shared.lds")

crypto/fipsmodule/bcm.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626

2727
// On Windows place the bcm code in a specific section that uses Grouped Sections
2828
// to control the order. $b section will place bcm in between the start/end markers
29-
// which are in $a and $z.
30-
#if defined(BORINGSSL_FIPS) && defined(OPENSSL_WINDOWS)
29+
// which are in $a and $z. These pragmas are supported by MSVC and Clang on Windows,
30+
// but not by MinGW GCC.
31+
#if defined(BORINGSSL_FIPS) && (defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32)))
3132
#pragma code_seg(".fipstx$b")
3233
#pragma data_seg(".fipsda$b")
3334
#pragma const_seg(".fipsco$b")
@@ -264,7 +265,7 @@ WEAK_SYMBOL_FUNC(void, AWS_LC_fips_failure_callback, (const char* message))
264265
#endif
265266
#endif
266267

267-
#if defined(_MSC_VER)
268+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
268269
#pragma section(".CRT$XCU", read)
269270
static void BORINGSSL_bcm_power_on_self_test(void);
270271
__declspec(allocate(".CRT$XCU")) void(*fips_library_init_constructor)(void) =

crypto/fipsmodule/fips_shared_library_marker.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <stdint.h>
1919

2020
#if defined(AWSLC_FIPS_SHARED_START)
21-
#if defined(_MSC_VER)
21+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
2222
#pragma code_seg(".fipstx$a")
2323
#pragma data_seg(".fipsda$a")
2424
#pragma const_seg(".fipsco$a")
@@ -34,14 +34,14 @@
3434
const uint8_t *BORINGSSL_bcm_text_start(void) {
3535
return NULL;
3636
}
37-
#if defined(_MSC_VER)
37+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
3838
__declspec(allocate(".fipsco$a"))
3939
#endif
4040
const uint8_t BORINGSSL_bcm_rodata_start[16] =
4141
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
4242

4343
#elif defined(AWSLC_FIPS_SHARED_END)
44-
#if defined(_MSC_VER)
44+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
4545
#pragma code_seg(".fipstx$z")
4646
#pragma data_seg(".fipsda$z")
4747
#pragma const_seg(".fipsco$z")
@@ -57,7 +57,7 @@ const uint8_t BORINGSSL_bcm_rodata_start[16] =
5757
const uint8_t *BORINGSSL_bcm_text_end(void){
5858
return NULL;
5959
}
60-
#if defined(_MSC_VER)
60+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
6161
__declspec(allocate(".fipsco$z"))
6262
#endif
6363
const uint8_t BORINGSSL_bcm_rodata_end[16] =

crypto/fipsmodule/fips_shared_support.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
// boundary (.fipsco). If it were placed inside the FIPS rodata boundary, the
2020
// integrity check would hash the expected value itself, creating a circular
2121
// dependency that can never be satisfied.
22-
#if defined(_MSC_VER)
22+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
2323
#pragma const_seg()
2424
#endif
2525

crypto/fipsmodule/rand/entropy/tree_drbg_jitter_entropy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ int tree_jitter_initialize(struct entropy_source_t *entropy_source) {
328328
return 1;
329329
}
330330

331-
#if defined(_MSC_VER)
331+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
332332
#pragma section(".CRT$XCU", read)
333333
static void tree_jitter_free_global_drbg(void);
334334
static void windows_install_tree_jitter_free_global_drbg(void) {

crypto/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ static inline uint64_t CRYPTO_subc_u64(uint64_t x, uint64_t y, uint64_t borrow,
12971297
#if defined(AWSLC_FIPS_FAILURE_CALLBACK)
12981298
void AWS_LC_FIPS_failure(const char* message);
12991299
#else
1300-
#if defined(_MSC_VER)
1300+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
13011301
__declspec(noreturn) void AWS_LC_FIPS_failure(const char* message);
13021302
#else
13031303
void AWS_LC_FIPS_failure(const char* message) __attribute__((noreturn));

util/fipstools/acvp/modulewrapper/main.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <iostream>
1717
#include <string>
1818

19-
#if defined(_MSC_VER)
19+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
2020
#include <fcntl.h>
2121
#include <io.h>
2222
#include <stdio.h>
@@ -66,7 +66,7 @@ int main(int argc, char **argv) {
6666
return 4;
6767
}
6868

69-
#if defined(_MSC_VER)
69+
#if defined(_MSC_VER) || (defined(__clang__) && defined(_WIN32))
7070
if (_setmode(_fileno(stdin), _O_BINARY) < 0 ||
7171
_setmode(_fileno(stdout), _O_BINARY) < 0) {
7272
fprintf(stderr, "Setting binary mode to stdin/stdout failed.\n");

0 commit comments

Comments
 (0)