# aws-lc-fips-sys

[![crates.io](https://img.shields.io/crates/v/aws-lc-fips-sys.svg)](https://crates.io/crates/aws-lc-fips-sys)
[![GitHub](https://img.shields.io/badge/GitHub-aws%2Faws--lc--rs-blue)](https://github.com/aws/aws-lc-rs)

**Autogenerated** low-level AWS-LC FIPS bindings for the Rust programming language. We do not recommend directly relying
on these bindings.

[Documentation](https://github.com/aws/aws-lc).

## Native build metadata

Downstream Cargo build scripts that compile additional C code against this
AWS-LC FIPS build can use the exported `include`, `libdir`, `libcrypto_path`,
`link_kind`, and `system_libs` metadata. When the `ssl` feature is enabled,
`libssl_path` is also exported. Cargo exposes these values to direct dependents
as versioned `DEP_AWS_LC_FIPS_*` environment variables.

`link_kind` is `static` or `dylib`, usable directly as the `<kind>` in a
`cargo:rustc-link-lib=<kind>=<name>` directive.

`system_libs` is a comma-separated (possibly empty) list of additional system
libraries AWS-LC requires; a build script linking the static `libcrypto_path`
artifact must link these too. On `*-windows-gnu` it is `bcrypt`, which MinGW/GCC
does not pick up from AWS-LC's `#pragma comment(lib, "bcrypt.lib")`.

On Windows, `libcrypto_path` and `libssl_path` refer to the link-time artifact
-- for dynamic builds this is the import library (`*.lib` for MSVC,
`lib*.dll.a` for MinGW), not the runtime DLL. For builds from source the DLL is
placed alongside the import library in `libdir`; when linking against a
pre-installed AWS-LC (`AWS_LC_FIPS_SYS_SYSTEM_DIR`) the DLL follows the CMake
install layout and lives in `bin/` instead.

## FIPS

The aws-lc-fips-sys crate provides bindings to the latest version of the AWS-LC-FIPS module that
has completed FIPS validation testing by an accredited lab and has been submitted to NIST for
certification. This will continue to be the case as we periodically submit new versions of
the AWS-LC-FIPS module to NIST for certification. Currently, aws-lc-fips-sys binds to
[AWS-LC-FIPS 3.0.x](https://github.com/aws/aws-lc/tree/fips-2024-09-27).

Consult with your local FIPS compliance team to determine the version of AWS-LC-FIPS module that you require. Consumers
needing to remain on a previous version of the AWS-LC-FIPS module should pin to specific versions of aws-lc-rs to avoid
automatically being upgraded to a newer module version.
(See [cargo’s documentation](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html)
on how to specify dependency versions.)

| AWS-LC-FIPS module | aws-lc-rs |
|--------------------|-----------|
| 2.0.x              | \<1.12.0  |
| 3.0.x              | *latest*  |

Refer to the
[NIST Cryptographic Module Validation Program's Modules In Progress List](https://csrc.nist.gov/Projects/cryptographic-module-validation-program/modules-in-process/Modules-In-Process-List)
for the latest status of the static or dynamic AWS-LC Cryptographic Module. Please see the
[FIPS.md in the aws-lc repository](https://github.com/aws/aws-lc/blob/main/crypto/fipsmodule/FIPS.md)
for relevant security policies and information on supported operating environments.
We will also update our release notes and documentation to reflect any changes in FIPS certification status.

## Building and Bindings

This crate contains source code from a FIPS branch of AWS-LC for building and for bindings generation. A
specialized FIPS build is performed. Bindings for some platforms are pre-generated.

### Pregenerated Bindings Availability

| Targets                    |
|----------------------------|
| aarch64_apple_darwin       |
| aarch64_unknown_linux_gnu  |
| aarch64_unknown_linux_musl |
| x86_64_apple_darwin        |
| x86_64_unknown_linux_gnu   |
| x86_64_unknown_linux_musl  |

### Prebuilt NASM objects

Prebuilt NASM objects are *not* available for this crate.

### Tested AWS-LC FIPS Build Environments

`aws-lc-fips-sys` currently relies on the AWS-LC FIPS static build, please see our CI documentation
at [AWS-LC](https://github.com/aws/aws-lc/tree/main/tests/ci#unit-tests).

## Using a system-installed AWS-LC FIPS module

If you already have an AWS-LC FIPS installation (built and installed with `-DFIPS=1`), you can
link against it instead of building from the bundled source. Set `AWS_LC_FIPS_SYS_SYSTEM_DIR` to
the install prefix:

```shell
AWS_LC_FIPS_SYS_SYSTEM_DIR=/path/to/aws-lc-fips-install cargo build
```

### Automatic detection

`AWS_LC_FIPS_SYS_SYSTEM_DIR` need not be set explicitly. When it is unset, the
build script tries to discover a usable AWS-LC FIPS install from common
OpenSSL-compatible environment variables and pkg-config metadata, and links it
if found; otherwise it builds the bundled source. Discovery order, highest
precedence first:

1. `AWS_LC_FIPS_SYS_SYSTEM_DIR` — explicit prefix (above); problems with an
   explicit prefix are fatal, never a silent fallback.
2. `OPENSSL_DIR` — install prefix.
3. `OPENSSL_INCLUDE_DIR` / `OPENSSL_LIB_DIR` — independent header and library
   directories. Either may be set on its own; the unset half is derived from
   `OPENSSL_DIR`, matching `openssl-sys`.
4. pkg-config (Unix only) — probes `openssl`, `aws-lc`, `libcrypto`, then
   `libcrypto-awslc`, used only when the variables above are unset; honors
   `PKG_CONFIG_ALLOW_CROSS`.

Each `OPENSSL_*` variable also honors a target-suffixed form using Cargo's
normalized target triple (e.g. `OPENSSL_DIR_aarch64_unknown_linux_gnu`), checked
first.

For `OPENSSL_INCLUDE_DIR` + `OPENSSL_LIB_DIR`, automatic binding lookup expects
`OPENSSL_INCLUDE_DIR` to be `<prefix>/include` or AWS-LC's cohabiting
`<prefix>/include/aws-lc` layout, and searches
`<prefix>/share/rust/aws_lc_bindings.rs`. If bindings live elsewhere, set
`AWS_LC_FIPS_SYS_SYSTEM_BINDINGS` explicitly.

A discovered install is **adopted only if** it is genuinely AWS-LC (carries the
`OPENSSL_IS_AWSLC` marker), is a FIPS build whose [FIPS module version](#version-compatibility)
meets the minimum, passes [FIPS verification](#fips-verification), and ships
usable [bindings](#bindings). A non-FIPS build, a system OpenSSL, a too-old
module version, or a binding-less install is ignored and the build falls back
to source — detection never fails the build on its own.

Control detection with `AWS_LC_FIPS_SYS_USE_SYSTEM`:

* **unset** — detect; link a usable system FIPS install if found, else build from source.
* **`0`** — skip detection; always build from source.
* **`1`** — require a system FIPS install; fail the build if none is found.

`AWS_LC_FIPS_SYS_USE_SYSTEM` governs only the *automatic* detection that runs
when no explicit prefix is given. Setting both `AWS_LC_FIPS_SYS_SYSTEM_DIR` and
`AWS_LC_FIPS_SYS_USE_SYSTEM=0` is contradictory and fails the build.

Detection is quiet by default: when no system install is adopted the build
simply falls back to source. To see which locations were probed and why each
candidate was rejected, build verbosely with `cargo build -vv`.

The layout, FIPS verification, bindings, and version requirements described
below apply to auto-detected installs exactly as they do to
`AWS_LC_FIPS_SYS_SYSTEM_DIR`.

The install directory must contain `include/openssl/base.h` and a `lib/` (or `lib64/`) directory
holding `libcrypto` (and `libssl` when the `ssl` feature is enabled). The structure mirrors what
`aws-lc-sys` accepts — see [aws-lc-sys/README.md](../aws-lc-sys/README.md) for the full layout.

### FIPS verification

The build script links a small C probe against the install's `libcrypto` and calls
`BORINGSSL_integrity_test()`, which is exported only by FIPS, non-ASAN AWS-LC builds. When the
build host can run the target binary directly, or through `CARGO_TARGET_<TRIPLE>_RUNNER`, the probe
also requires `FIPS_mode() != 0`.

A startup check is also linked into dependent binaries. It calls `FIPS_mode()` at process startup
and aborts if the runtime library is not in FIPS mode, catching issues the build-time probe cannot
see, such as deployment-host mismatches or shared-library shadowing. If the build-time probe links
but cannot be launched, the build continues and relies on this startup check.

### Runtime library path (shared installs)

When linking a shared `libcrypto` (the required form for FIPS on macOS and Windows), the install's
library directory is not embedded in the consumer binary, so the dynamic loader must be able to
find it at runtime. Otherwise a different `libcrypto` may be loaded — on macOS the build-host's
`@rpath` install name can resolve to an unrelated library. Make the install discoverable via
`LD_LIBRARY_PATH`/`DYLD_LIBRARY_PATH=<prefix>/lib`, an rpath in your own binary
(`RUSTFLAGS="-C link-arg=-Wl,-rpath,<prefix>/lib"`), or a standard system library path. Static
installs (Linux) are unaffected.

### Bindings

This path requires pre-generated bindings; it does not invoke `bindgen` itself. Either:

1. Install AWS-LC with `-DGENERATE_RUST_BINDINGS=ON` (AWS-LC v1.68.0+) so the conventional
   `share/rust/aws_lc_bindings.rs` is populated; or
2. Set `AWS_LC_FIPS_SYS_SYSTEM_BINDINGS=/path/to/bindings.rs` to point at a bindings file you
   produced separately.

The bindings must match the install's `BORINGSSL_PREFIX` setting. Generate bindings for the exact
install you intend to link; the bindings shipped inside this crate are for the bundled,
version-stamped prefix and are not suitable for an arbitrary system install.

### Version compatibility

FIPS installs are gated on the AWS-LC **FIPS module version** (an integer
identifying a validation submission, decoupled from the library version; see
[aws/aws-lc#3211](https://github.com/aws/aws-lc/pull/3211)), which must be at
least the minimum supported by this crate (currently `3`). It is read from
`AWSLC_FIPS_VERSION_NUMBER`, falling back to the major of
`AWSLC_VERSION_NUMBER_STRING` on older branches (e.g. FIPS 3.x → `3`). To bypass
this check (not recommended), set `AWS_LC_FIPS_SYS_SYSTEM_SKIP_VERSION_CHECK=1`.

## Optimizing for binary size

Unlike `aws-lc-sys`, this crate never enables the size optimization
automatically based on opt-level. Because the optimization changes the
compiled FIPS module, it must be explicitly requested by setting
`AWS_LC_FIPS_SYS_SMALL=1`. This applies compile-time defines that reduce
binary size at the cost of performance (primarily elliptic curve operations).

**Note:** Enabling this optimization changes the compiled FIPS module and may
affect FIPS validation status. A build-time warning is emitted when it is
active. Consult your compliance requirements before shipping this configuration
in a FIPS-regulated environment.

See [aws-lc-sys/README.md](../aws-lc-sys/README.md#optimizing-for-binary-size)
for details on the size reduction, performance trade-offs, and affected
algorithms.

## Build Prerequisites

Since this crate builds AWS-LC as a native library, all build tools needed to build AWS-LC are applicable to
`aws-lc-fips-sys` as well. This includes Go and Perl, which are hard dependencies for the AWS-LC FIPS build.

[Building AWS-LC](https://github.com/aws/aws-lc/blob/main/BUILDING.md)

If you use a different build combination for FIPS and would like us to support it, please open an issue to us
at [AWS-LC](https://github.com/aws/aws-lc/issues/new?assignees=&labels=&template=build-issue.md&title=).

## Security Notification Process

If you discover a potential security issue in *AWS-LC* or *aws-lc-fips-sys*, we ask that you notify AWS
Security via our
[vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/).
Please do **not** create a public GitHub issue.

If you package or distribute *aws-lc-fips-sys*, or use *aws-lc-fips-sys* as part of a large multi-user service,
you may be eligible for pre-notification of future *aws-lc-fips-sys* releases.
Please contact aws-lc-pre-notifications@amazon.com.

## Contribution

See contributing file at [AWS-LC](https://github.com/aws/aws-lc/blob/main/CONTRIBUTING.md)

## Licensing

See license at [AWS-LC](https://github.com/aws/aws-lc/blob/main/LICENSE)
