intel / ACON

Apache License 2.0
56 stars 16 forks source link

acond: FIPS and Reproducible build #9

Closed binxing closed 1 year ago

binxing commented 1 year ago

This issue captures/discusses options for building acond to achieve

Minimal TCB Size

The objective is to achieve minimal initrd image but NOT acond binary.

Generally, static linking yields smaller acond binary because unused functions from standard libraries (e.g., libc, libssl, etc.). But the user may copy additional executables into initrd for functionalities like disk encryption or SSH support, and in those cases dynamic linking may reduce the overall size by sharing common libraries among all the executables.

Linking acond Statically

The size of libc affects acond binary size significantly. musl-libc is famous for its small size (when compared with glibc) so is preferred.

The easiest way to build acond as a static executable is to build it on musl based Linux distro like Alpine, using Rust target x86_64-unknown-linux-musl.

cargo build --release --target x86_64-unknown-linux-musl

Please note rustc generates statically linked PIE (Position Independent Executable) on musl target by default. PIEs must be relocated before being executed, hence acond by default still requires the dynamic linker (which is the musl libc shared object) to run. The flag -Crelocation-model=static instructs rustc to create the executable with a fixed base address to avoid depending on the dynamic linker.

Linking acond Dynamically

The command below links acond to the system libraries dynamically.

CARGO_BUILD_RUSTFLAGS=-Ctarget-feature=-crt-static cargo build --release

The flag -Ctarget-feature=-crt-static is necessary on musl targets where static linking is the default.

FIPS Compliance

OpenSSL is undergoing the certification process and likely to be the first crypto library to receive FIPS-140-3 certificates.

OpenSSL is certifying its FIPS module (fips.so), meaning any application must use the FIPS module as-is to stay compliant with FIPS, and that implies dynamic linking.

OpenSSL is only validated on Ubuntu and Debian distros, so a FIPS compliant acond must be built on Ubuntu/Debian.

Reproducible Build

nix seems the solution at first glance. However, it provides only glibc based OpenSSL (i.e., no musl based OpenSSL) build in its repo without static OpenSSL libs. With that said, the only choice on nix is to dynamically link to glibc, and that makes initrd much bigger. It also lacks FIPS support.

An alternative is the rust container, which has a tag for every rust release on every supported Linux distro. Builds seem reproducible for acond source. Please note such reproducibility is incomplete as it cannot prove the external libs (libc and OpenSSL libs) were built from particular source. We will have to rely on the Linux distro for reproducibility of those libs.

Conclusion/Proposal

Both static and dynamic linking should be supported.

Tasks

binxing commented 1 year ago

Team has agreed on the proposal. Task listed created.

binxing commented 1 year ago

Hi @xiangquanliu and @billionairiam, I made a mistake in the opening comment about PIE. Probably I wasn't using the lastest rustc. It turns out on GCC has this relatively newer option -static-pie that embeds relocation logic in the executable's startup code, so PIEs created with -static-pie do NOT require a dynamic loader. And it seems the latest rust-1.72.0 makes use of that option, hence -Crelocation-model=static is unnecessary and in fact breaks the build. The opening comment has been updated and I'll update acond's README soon.