# aws-lc-sys

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

**Autogenerated** Low-level bindings to the AWS-LC library for the Rust programming language. The versioning for this
crate will be unstable.
New releases of AWS-LC will correspond to a new `0.x.0` version of this crate. Features and/or fixes from AWS-LC
will not be backported to older versions of this crate. We do not recommend taking a direct dependency on this crate.

See our [User Guide](https://aws.github.io/aws-lc-rs/) for guidance on installing build requirements.

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

## Native build metadata

Downstream Cargo build scripts that compile additional C code against this
AWS-LC 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_*` 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_SYS_SYSTEM_DIR`) the DLL follows the CMake
install layout and lives in `bin/` instead.

## Build Support

This crate pulls in the source code of AWS-LC to build with it. Bindings for popular platforms are pre-generated.
To generate bindings for platforms where pre-generated bindings aren't available, you can either specify our `bindgen`
feature or install the [bindgen-cli](https://crates.io/crates/bindgen-cli).

### Pregenerated Bindings Availability

Targets
-------------
aarch64_apple_darwin
aarch64_pc_windows_msvc
aarch64_unknown_linux_gnu
aarch64_unknown_linux_musl
i686_pc_windows_msvc
i686_unknown_linux_gnu
x86_64_apple_darwin
x86_64_pc_windows_gnu
x86_64_pc_windows_msvc
x86_64_unknown_linux_gnu
x86_64_unknown_linux_musl

### Use of prebuilt NASM objects

For Windows x86 and x86-64, NASM is required for assembly code compilation. On these platforms,
we recommend that you install [the NASM assembler](https://www.nasm.us/). If NASM is
detected in the build environment *it is used* to compile the assembly files. However,
if a NASM assembler is not available, and the "fips" feature is not enabled, then the build fails unless one of the
following conditions are true:

* You are building for `x86-64` and either:
    * The `AWS_LC_SYS_PREBUILT_NASM` environment variable is found and has a value of "1"; OR
    * `AWS_LC_SYS_PREBUILT_NASM` is *not found* in the environment AND the "prebuilt-nasm" feature has been enabled.

If the above cases apply, then the crate provided prebuilt NASM objects will be used for the build. To prevent usage of
prebuilt NASM
objects, install NASM in the build environment and/or set the variable `AWS_LC_SYS_PREBUILT_NASM` to `0` in the build
environment to prevent their use.

#### About prebuilt NASM objects

Prebuilt NASM objects are generated using automation similar to the crate provided pregenerated bindings. See the
repository's
[GitHub workflow configuration](https://github.com/aws/aws-lc-rs/blob/main/.github/workflows/sys-bindings-generator.yml)
for more information.
The prebuilt NASM objects are checked into the repository
and are [available for inspection](https://github.com/aws/aws-lc-rs/tree/main/aws-lc-sys/builder/prebuilt-nasm).
For each PR submitted,
[CI verifies](https://github.com/aws/aws-lc-rs/blob/main/.github/workflows/tests.yml)
that the NASM objects newly built from source match the NASM objects currently in the repository.

## Using a system-installed AWS-LC

If you have an existing AWS-LC installation (built and installed via CMake),
you can link against it instead of building AWS-LC from the bundled source.
Set `AWS_LC_SYS_SYSTEM_DIR` to the install prefix:

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

### Automatic detection

You don't have to set `AWS_LC_SYS_SYSTEM_DIR` explicitly. When it is unset, the
build script tries to discover a usable AWS-LC from common OpenSSL-compatible
environment variables and pkg-config metadata, and links it if found; otherwise
it falls back to building the bundled source.
This makes the crate link against the AWS-LC provided by the surrounding
environment (for example, the AWS-LC present in a build's dependency closure)
with no extra configuration. Discovery order, highest precedence first:

1. `AWS_LC_SYS_SYSTEM_DIR` — explicit install prefix (above). Any problem with
   an explicit prefix is a hard error, 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 none of the variables above are set.
   Cross-compilation follows pkg-config's own rule (set
   `PKG_CONFIG_ALLOW_CROSS=1` to allow it).

Each `OPENSSL_*` variable also honors a target-suffixed form using Cargo's
normalized target triple (e.g. `OPENSSL_DIR_x86_64_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_SYS_SYSTEM_BINDINGS` explicitly.

A discovered install is **adopted only if it is genuinely AWS-LC** (carries the
`OPENSSL_IS_AWSLC` marker), satisfies the [version requirement](#version-compatibility),
and ships usable [bindings](#bindings-resolution). Anything else — a system
OpenSSL, an AWS-LC older than the minimum, or one without bindings — is ignored
and the build falls back to source. Auto-detection never fails the build on its
own; it only ever *adds* the option of linking a suitable system install.

Use `AWS_LC_SYS_USE_SYSTEM` to control this behavior:

* **unset** — detect; link a usable system AWS-LC if found, else build from source.
* **`0`** (or `false`/`no`/`off`) — skip detection entirely; always build from source.
* **`1`** (or `true`/`yes`/`on`) — require a system AWS-LC; if none is found, the
  build fails instead of falling back to source.

`AWS_LC_SYS_USE_SYSTEM` governs only the *automatic* detection that runs when no
explicit prefix is given. Setting both `AWS_LC_SYS_SYSTEM_DIR` and
`AWS_LC_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, linkage, bindings, and version requirements described below apply
to auto-detected installs exactly as they do to `AWS_LC_SYS_SYSTEM_DIR`.

The install directory must contain:

* `include/openssl/base.h` — used to detect the `OPENSSL_IS_AWSLC` marker and
  the AWS-LC version (`AWSLC_VERSION_NUMBER_STRING`).
* `lib/` (or `lib64/` for 64-bit targets, when present) containing `libcrypto`.
  When the `ssl` feature is enabled, `libssl` is also required.

Static vs. dynamic linking honors `AWS_LC_SYS_STATIC` (the same variable used
when building from source). When both static and dynamic libraries are present
the preferred form is selected; if only one is present and `AWS_LC_SYS_STATIC`
is unset, that form is used with a warning. If `AWS_LC_SYS_STATIC` is set
explicitly and the requested form is not present, the build fails rather than
silently using the wrong linkage.

On Windows with the MSVC toolchain, both a real static archive and a DLL
import library are named `{name}.lib` and live under `lib/`. The two are
distinguished by the presence of a sibling `bin/{name}.dll` produced by
CMake for shared builds: a `.lib` with such a sibling is classified as the
dynamic artifact, and one without is classified as static.

When linking dynamically, the runtime loader needs to find the shared library
at execution time. The build script does not embed an rpath, so configure
your environment accordingly:

* Linux: `LD_LIBRARY_PATH=<install_dir>/lib`
* macOS: `DYLD_LIBRARY_PATH=<install_dir>/lib`
* Windows: add `<install_dir>/bin` to `PATH`

If the install was built with a `BORINGSSL_PREFIX`, the symbol prefix is
detected from `include/openssl/boringssl_prefix_symbols.h` and reported in
the build log. Note that AWS-LC's CMake does not rename the library file
itself when prefixing — only the symbols inside — so no special handling
is required at link time. The pre-generated bindings shipped by AWS-LC's
CMake (`share/rust/aws_lc_bindings.rs`) are already prefix-aware.

### Bindings resolution

This path requires pre-generated bindings; it does not invoke `bindgen` itself.
Bindings are resolved in this order:

1. **`AWS_LC_SYS_SYSTEM_BINDINGS`** — explicit path to a pre-generated
   `bindings.rs`. A misconfigured path is a hard error.
2. **`<install_dir>/share/rust/aws_lc_bindings.rs`** — populated by AWS-LC's
   CMake install when built with `-DGENERATE_RUST_BINDINGS=ON`
   (AWS-LC v1.68.0+, see [aws-lc#2999](https://github.com/aws/aws-lc/pull/2999)).

If neither is available the build fails with guidance on how to proceed.

### Version compatibility

The installed AWS-LC version must be at least the minimum supported by this
crate, independent of the bundled version. That floor is declared as the
`MINIMUM_AWS_LC_VERSION` constant in `builder/system_library.rs`. To bypass this
check (not recommended), set `AWS_LC_SYS_SYSTEM_SKIP_VERSION_CHECK=1`.

### Limitations

When the `ssl` feature is enabled, the pre-generated bindings file must
cover both `libcrypto` and `libssl`. AWS-LC's `-DGENERATE_RUST_BINDINGS=ON`
produces such a combined file by default; if you supply your own bindings
via `AWS_LC_SYS_SYSTEM_BINDINGS`, ensure they include the `ssl` symbols
or you may get link errors when the `ssl` feature is on.

## Optimizing for binary size

When you build with `opt-level = "s"` or `opt-level = "z"` (Cargo's
size-optimizing profiles), `aws-lc-sys` automatically applies compile-time
defines that replace high-performance implementations with smaller generic
equivalents. No configuration is needed -- set the opt-level in your
`Cargo.toml` profile:

```toml
[profile.release]
opt-level = "z"
```

On x86_64 Linux, this typically reduces the aws-lc footprint by ~60-70%.
aarch64 sees a ~40% reduction. The effect is platform-dependent -- x86_64
benefits most because disabling AVX-512 assembly removes large vectorized
routines.

Key properties:

* **Automatic.** Triggered by `opt-level = "s"` or `"z"`.
* **Overridable.** Set `AWS_LC_SYS_SMALL=1` to force the size-optimized
  build regardless of opt-level, or `AWS_LC_SYS_SMALL=0` to prevent it
  even when the opt-level would otherwise trigger it.
* **Behavior-preserving.** All algorithms remain available; outputs are
  identical.
* **Performance trade-off.** Elliptic curve operations (ECDSA, ECDH) are
  significantly slower due to the removal of precomputed tables -- expect
  P-256 operations to be roughly 2-3x slower and P-384 roughly 3-6x
  slower. Symmetric operations (AES-GCM, SHA) and RSA are largely
  unaffected on aarch64; on x86_64 bulk throughput may decrease due to
  the removal of AVX-512 code paths.
* **Windows NASM.** Source-built NASM assembly honors the size-optimization
  definitions. Prebuilt NASM objects cannot be reconfigured; install NASM
  to obtain the full assembly size reduction on Windows.
* **FIPS.** `aws-lc-fips-sys` never enables this automatically; it requires
  an explicit `AWS_LC_FIPS_SYS_SMALL=1`. See its README for details.

## Build Prerequisites

Since this crate builds AWS-LC as a native library, most build tools needed to build AWS-LC are applicable
to `aws-lc-sys` as well. Go and Perl aren't absolutely necessary for `aws-lc-sys`, as AWS-LC provides generated build
files.

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

AWS-LC is tested on a variety of C/C++ compiler, OS, and CPU combinations. For a complete list of tested combinations
see [tests/ci/Readme.md](https://github.com/aws/aws-lc/tree/main/tests/ci#unit-tests). If you use a different build
combination 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=).

## Building with a FIPS-validated module

This crate does not offer the AWS-LC FIPS build. To use AWS-LC FIPS, please use the FIPS version of this crate,
available at [aws-lc-fips-sys](https://crates.io/crates/aws-lc-fips-sys).

## Post-Quantum Cryptography

Details on the post-quantum algorithms supported by aws-lc-sys can be found at
[PQREADME](https://github.com/aws/aws-lc/tree/main/crypto/fipsmodule/PQREADME.md).

## Security Notification Process

If you discover a potential security issue in *AWS-LC* or *aws-lc-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-sys*, or use *aws-lc-sys* as part of a large multi-user service,
you may be eligible for pre-notification of future *aws-lc-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)
