Skip to content

Commit

Permalink
add SymCrypt-debuginfo package
Browse files Browse the repository at this point in the history
  • Loading branch information
tobiasb-ms committed Oct 12, 2024
1 parent 245c3b9 commit 1ec9e7e
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
From a91f9a55e6b8b01511538827005a6e948ccf6e27 Mon Sep 17 00:00:00 2001
From: Tobias Brick <[email protected]>
Date: Sat, 12 Oct 2024 02:06:21 +0000
Subject: [PATCH] add build flags to prevent stripping and post processing

---
BUILD.md | 2 ++
CMakeLists.txt | 14 ++++++++++++++
modules/linux/common/ModuleCommon.cmake | 4 ++--
scripts/build.py | 8 ++++++++
4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/BUILD.md b/BUILD.md
index e7f0618..a4984da 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -63,6 +63,8 @@ and building the Linux modules with FIPS integrity checks.
* To cross-compile for Linux ARM64, you must also use `--toolchain=cmake-configs/Toolchain-Clang-ARM64.cmake`
* `-DSYMCRYPT_USE_ASM=<ON|OFF>` to choose whether to use assembly optimizations. Defaults to `ON`.
* `-DSYMCRYPT_FIPS_BUILD=<ON|OFF>` to choose whether to enable FIPS self-tests in the SymCrypt shared object module. Defaults to `ON`. Currently only affects Linux builds.
+ * `-DSYMCRYPT_STRIP_BINARY=<ON|OFF>` to choose whether to strip the binary. Defaults to `ON`.
+ * `-DSYMCRYPT_FIPS_POSTPROCESS=<ON|OFF>` to choose whether to run the FIPS postprocess script. Defaults to `ON`.
* For a release build, specify `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
1. `cmake --build bin`
* Optionally, for a release build on Windows, specify `--config Release`
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6da485d..1533e9d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,6 +54,18 @@ if(SYMCRYPT_FIPS_BUILD)
add_compile_options(-DSYMCRYPT_DO_FIPS_SELFTESTS=1)
endif()

+option(
+ SYMCRYPT_STRIP_BINARY
+ "When enabled, SymCrypt will strip the binary in release mode."
+ ON
+)
+
+option(
+ SYMCRYPT_FIPS_POSTPROCESS
+ "When enabled, SymCrypt will do postprocessing the binary for FIPS integrity verification."
+ ON
+)
+
option(
SYMCRYPT_TEST_LEGACY_IMPL
"When enabled, the SymCrypt unit tests will be linked against and configured to run compatibility and performance tests on the legacy
@@ -94,6 +106,8 @@ message(STATUS "Host: ${CMAKE_HOST_SYSTEM_NAME} ${CMAKE_HOST_SYSTEM_PROCESSOR}")
message(STATUS "Target: ${CMAKE_SYSTEM_NAME} ${SYMCRYPT_TARGET_ARCH} ${SYMCRYPT_TARGET_ENV}")
message(STATUS "ASM optimizations: ${SYMCRYPT_USE_ASM}")
message(STATUS "FIPS build: ${SYMCRYPT_FIPS_BUILD}")
+message(STATUS "Strip binary: ${SYMCRYPT_STRIP_BINARY}")
+message(STATUS "FIPS postprocess: ${SYMCRYPT_FIPS_POSTPROCESS}")

# Set output directories binaries
# Note: we use a generator expression because "Multi-configuration generators [e.g. Visual Studio]
diff --git a/modules/linux/common/ModuleCommon.cmake b/modules/linux/common/ModuleCommon.cmake
index ced60ac..7d626c0 100644
--- a/modules/linux/common/ModuleCommon.cmake
+++ b/modules/linux/common/ModuleCommon.cmake
@@ -57,7 +57,7 @@ set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(${TARGET_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR})


-if(CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo")
+if(CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo" AND SYMCRYPT_STRIP_BINARY)
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
@@ -69,7 +69,7 @@ if(CMAKE_BUILD_TYPE MATCHES "Release|RelWithDebInfo")
)
endif()

-if(SYMCRYPT_FIPS_BUILD)
+if(SYMCRYPT_FIPS_BUILD AND SYMCRYPT_FIPS_POSTPROCESS)
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
diff --git a/scripts/build.py b/scripts/build.py
index bbf0c89..48a7146 100755
--- a/scripts/build.py
+++ b/scripts/build.py
@@ -101,6 +101,12 @@ def configure_cmake(args : argparse.Namespace) -> None:
if not args.fips:
cmake_args.append("-DSYMCRYPT_FIPS_BUILD=OFF")

+ if not args.strip_binary:
+ cmake_args.append("-DSYMCRYPT_STRIP_BINARY=OFF")
+
+ if not args.fips_postprocess:
+ cmake_args.append("-DSYMCRYPT_FIPS_POSTPROCESS=OFF")
+
if args.test_legacy_impl:
cmake_args.append("-DSYMCRYPT_TEST_LEGACY_IMPL=ON")

@@ -215,6 +221,8 @@ def main() -> None:
parser_cmake.add_argument("--cxx", type = str, help = "Specify the C++ compiler to use. If not provided, uses platform default.")
parser_cmake.add_argument("--no-asm", action = "store_false", dest = "asm", help = "Disable handwritten ASM optimizations.", default = True)
parser_cmake.add_argument("--no-fips", action = "store_false", dest = "fips", help = "Disable FIPS selftests and postprocessing of binary. Currently only affects Linux targets.", default = True)
+ parser_cmake.add_argument("--no-strip-binary", action = "store_false", dest = "strip_binary", help = "Disable stripping of binary.", default = True)
+ parser_cmake.add_argument("--no-fips-postprocess", action = "store_false", dest = "fips_postprocess", help = "Disable FIPS postprocessing of binary.", default = True)
parser_cmake.add_argument("--test-legacy-impl", action = "store_true",
help = "Build unit tests with support for legacy Windows cryptographic implementations. Requires access to private static libraries.",
default = False)
--
2.39.4

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
From a3741fb82606395f3ef7f079f7bd6ed4891107ce Mon Sep 17 00:00:00 2001
From: Tobias Brick <[email protected]>
Date: Sat, 12 Oct 2024 00:32:43 +0000
Subject: [PATCH] add parameter to process_fips_module to specify the
processing directory

---
scripts/process_fips_module.py | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/scripts/process_fips_module.py b/scripts/process_fips_module.py
index 53dcaad..87f521a 100755
--- a/scripts/process_fips_module.py
+++ b/scripts/process_fips_module.py
@@ -16,6 +16,7 @@ import io
import logging
import os
import secrets
+import shutil
import stat
import struct

@@ -382,6 +383,8 @@ def main():

parser = argparse.ArgumentParser(description = "Postprocess SymCrypt shared object module")
parser.add_argument("input", type=str, help = "Path to SymCrypt module")
+ parser.add_argument("-p", "--processing-dir", type=str, default=None,
+ help = "Directory to store temporary debug files during processing. If unspecified, will use the processing directory in the same folder as input.")
parser.add_argument("-d", "--debug", action = "store_true",
help = "Enable debug output (also dumps hashable module contents to file)")

@@ -392,8 +395,8 @@ def main():
else:
logging.basicConfig(level = logging.INFO)

- debug_files_basename = os.path.join(
- os.path.dirname(args.input), "processing", os.path.basename(args.input))
+ processing_dir = args.processing_dir or os.path.join(os.path.dirname(args.input), "processing")
+ debug_files_basename = os.path.join(processing_dir, os.path.basename(args.input))
with open(args.input, "rb") as input_file:
buffer = input_file.read()
buffer_stream = io.BytesIO(buffer)
@@ -463,7 +466,11 @@ def main():
reset_jump_slots(elf_file, original_jump_slot_values)

# Copy the original input file to a backup file before writing our changes back to the original
- os.replace(args.input, debug_files_basename + ".bak")
+ # os.replace doesn't work across mount points so we manually delete and move the file.
+ backup_file = debug_files_basename + ".bak"
+ if os.path.exists(backup_file):
+ os.remove(backup_file)
+ shutil.move(args.input, backup_file)

with open(args.input, "wb") as output_file:
output_file.write(buffer_stream.getbuffer())
--
2.39.4

3 changes: 2 additions & 1 deletion SPECS/SymCrypt/SymCrypt.signatures.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"Signatures": {
"SymCrypt-103.4.2.tar.gz": "7cbcee7625fd1d99286e393a727504189dab4d407c6c3474bd2532d5ee231921",
"jitterentropy-library-3.3.1.tar.gz": "4a50cb02b4836cd5550016e2fc2263e6982abaa11467a9e1cea260c1c2f7d487"
"jitterentropy-library-3.3.1.tar.gz": "4a50cb02b4836cd5550016e2fc2263e6982abaa11467a9e1cea260c1c2f7d487",
"find-debuginfo": "b3e40f886735e44a434bb4a4925c4a497ab3288decd1c445c428b0d7397e9e03"
}
}
35 changes: 29 additions & 6 deletions SPECS/SymCrypt/SymCrypt.spec
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
%define debug_package %{nil}
Summary: A core cryptographic library written by Microsoft
Name: SymCrypt
Version: 103.4.2
Release: 1%{?dist}
Release: 2%{?dist}
License: MIT
Vendor: Microsoft Corporation
Distribution: Azure Linux
Group: System/Libraries
URL: https://github.com/microsoft/SymCrypt
Source0: https://github.com/microsoft/SymCrypt/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
Source1: https://github.com/smuellerDD/jitterentropy-library/archive/v3.3.1.tar.gz#/jitterentropy-library-3.3.1.tar.gz
Source2: find-debuginfo
Patch1: 0001-add-build-flags-to-prevent-stripping-and-post-proces.patch
Patch2: 0001-add-parameter-to-process_fips_module-to-specify-the-.patch
BuildRequires: cmake
%ifarch aarch64
BuildRequires: clang >= 12.0.1-4
Expand Down Expand Up @@ -40,26 +42,44 @@ A core cryptographic library written by Microsoft
%endif

%prep
%setup -q
%setup -q -a 1
%autosetup -a 1 -p1
# Create a symbolic link as if jitterentropy-library has been pulled in as git submodule
rm -rf 3rdparty/jitterentropy-library
ln -s ../jitterentropy-library-3.3.1 3rdparty/jitterentropy-library
# Copy the custom find-debuginfo script
cp %{SOURCE2} .

%build
SYMCRYPT_BRANCH=main \
SYMCRYPT_COMMIT_HASH=a84ffe1 \
SYMCRYPT_COMMIT_TIMESTAMP=2024-01-26T22:00:47-08:00 \
cmake -S . -B bin \
-DSYMCRYPT_TARGET_ARCH=%{symcrypt_arch} \
-DCMAKE_BUILD_TYPE=Release \
-DSYMCRYPT_STRIP_BINARY=OFF \
-DSYMCRYPT_FIPS_POSTPROCESS=OFF \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_C_COMPILER=%{symcrypt_cc} \
-DCMAKE_CXX_COMPILER=%{symcrypt_cxx} \
-DCMAKE_C_FLAGS="%{symcrypt_c_flags}" \
-DCMAKE_CXX_FLAGS="-Wno-unused-but-set-variable"

cmake --build bin

# Override the default find-debuginfo script to our own custom one, which is modified
# to allow us to keep symbols.
# Also add custom options to the call to find-debuginfo.
%define __find_debuginfo ./find-debuginfo
%define _find_debuginfo_opts --keep-symbol SymCryptVolatileFipsHmacKey --keep-symbol SymCryptVolatileFipsHmacKeyRva --keep-symbol SymCryptVolatileFipsBoundaryOffset --keep-symbol SymCryptVolatileFipsHmacDigest

# Override the default to allow us to do custom fips post-processing after debug info/stripping is done.
%define __spec_install_post \
%{?__debug_package:%{__debug_install_post}} \
%{__arch_install_post} \
%{__os_install_post} \
mkdir -p "bin/module/generic/processing" \
python3 "scripts/process_fips_module.py" "%{buildroot}%{_libdir}/libsymcrypt.so.%{version}" --processing-dir "bin/module/generic/processing" --debug \
%{nil}

%install
mkdir -p %{buildroot}%{_libdir}
mkdir -p %{buildroot}%{_includedir}
Expand All @@ -78,7 +98,10 @@ chmod 755 %{buildroot}%{_libdir}/libsymcrypt.so.%{version}
%{_includedir}/*

%changelog
* Wed Jun 25 2024 Maxwell Moyer-McKee <[email protected]> - 103.4.2-1
* Mon Oct 14 2024 Tobias Brick <[email protected]> - 103.4.2-2
- Add debuginfo package

* Wed Jun 26 2024 Maxwell Moyer-McKee <[email protected]> - 103.4.2-1
- Update SymCrypt to v103.4.2 for FIPS certification

* Thu Apr 25 2024 Maxwell Moyer-McKee <[email protected]> - 103.4.1-2
Expand Down
42 changes: 40 additions & 2 deletions SPECS/SymCrypt/find-debuginfo
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ automagically generates debug info and file lists
Options:
[--strict-build-id] [-g] [-r] [-m] [-i] [-n]
[--keep-section SECTION] [--remove-section SECTION]
[--keep-symbol SYMBOL]
[--g-libs]
[-j N] [--jobs N]
[-o debugfiles.list]
Expand All @@ -52,6 +53,9 @@ keep a (non-allocated) section in the main executable or explicitly
remove it into the .debug file. SECTION is an extended wildcard
pattern. Both options can be given more than once.
Use --keep-symbol SYMBOL to keep the symbol in the main executable.
This option can be given more than once.
The --strict-build-id flag says to exit with failure status if
any ELF binary processed fails to contain a build-id note.
Expand Down Expand Up @@ -99,7 +103,9 @@ EOF
}

# Figure out where we are installed so we can call other helper scripts.
install_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# SymCrypt-Specific: Because we have our own custom find-debuginfo, we need to use the
# location that the system version is installed at.
install_dir="$(cd "$(dirname "$(which find-debuginfo)")" && pwd)"

# With -g arg, pass it to strip on libraries or executables.
strip_g=false
Expand All @@ -113,6 +119,9 @@ strip_r=false
# keep or remove arguments to eu-strip.
keep_remove_args=

# keep or remove symbols arguments
keep_symbol_args=

# with -m arg, add minimal debuginfo to binary.
include_minidebug=false

Expand Down Expand Up @@ -225,6 +234,10 @@ while [ $# -gt 0 ]; do
keep_remove_args="${keep_remove_args} --remove-section $2"
shift
;;
--keep-symbol)
keep_symbol_args="${keep_symbol_args} --keep-symbol $2"
shift
;;
-j)
n_jobs=$2
shift
Expand Down Expand Up @@ -318,7 +331,32 @@ strip_to_debug()
$strip_glibs && case "$(file -bi "$2")" in
application/x-sharedlib*) g=-g ;;
esac
eu-strip --remove-comment $r $g ${keep_remove_args} -f "$1" "$2" || exit

# SymCrypt-Specific: We need to keep certain symbols in the stripped binary, which eu-strip does not support.
# So instead we use strip, but that has different semantics.
#
# Original eu-strip command:
# eu-strip --remove-comment $r $g ${keep_remove_args} ${keep_symbol_args} -f "$1" "$2" || exit
#
# Always remove the comment section
keep_remove_args="${keep_remove_args} --remove-section .comment"

# We don't set $r and $g in my testing. If we ever do set those, then this script
# will need to be modified to either find the equivalent in strip, or intentionally
# decide to not support these flags.
if [ -n "$r" ] || [ -n "$g" ]; then
echo >&2 "*** ERROR: strip_to_debug: r ('${r}') or g ('${r}') is set, but this script does not support it"
exit 2
fi

# strip has the -o flag instead of the -f flag, but the semantics are reversed
# For eu-strip, -f will extract the removed sections into the file given, leaving the original file alone.
# For strip, -o will write the stripped file to the given location, leaving original file alone.
# So we need to swap the arguments to strip.
mv "${2}" "${1}"

# The original cmake file for SymCrypt uses --strip-unneeded
strip --strip-unneeded ${keep_remove_args} ${keep_symbol_args} -o "$2" "$1" || exit
chmod 444 "$1" || exit
}

Expand Down

0 comments on commit 1ec9e7e

Please sign in to comment.