Building and Testing
Prerequisites
Install OpenSSL development headers and pkg-config:
# Fedora / RHEL
sudo dnf install openssl-devel
# Ubuntu / Debian
sudo apt install libssl-dev pkg-config
# macOS (Homebrew)
brew install openssl@3
export PKG_CONFIG_PATH="$(brew --prefix openssl@3)/lib/pkgconfig"
Verify the version (3.0.7 or later required):
pkg-config --modversion openssl
Minimum Rust version: 1.77 (required for c"..." C-string literal syntax).
Building
# Check all crates without producing binaries
cargo check --all-targets
# Build in release mode
cargo build --release
# Build and run the encrypt-demo example
cargo run -p encrypt-demo
Testing
# Run the full test suite
cargo test --all
# Run tests for a specific crate
cargo test -p native-ossl
# Run a specific test
cargo test -p native-ossl digest::tests::sha256_known_vector
The test suite requires a live OpenSSL library. Tests connect to no external services; all cryptographic operations are in-process.
Linting
# Run Clippy with pedantic lints as errors
cargo clippy --all-targets -- -D warnings
# Format check (does not modify files)
cargo fmt --all --check
# Apply formatting
cargo fmt --all
All pedantic Clippy lints are active workspace-wide. The only exception is
native-ossl-sys/src/lib.rs, which suppresses lints on bindgen-generated code
locally. Do not add blanket #![allow(...)] to any hand-written file.
bindgen Regeneration
Bindings are regenerated automatically by build.rs whenever OpenSSL headers
change. No manual step is required. To force regeneration:
cargo clean -p native-ossl-sys && cargo build -p native-ossl-sys
The generated file is written to $OUT_DIR/ossl_bindings.rs and is not committed
to the repository.
FIPS Mode
To test with the OpenSSL FIPS provider, install it:
# Fedora
sudo dnf install openssl-fips-provider
# Verify FIPS provider is loadable
openssl list -providers -provider fips
Run FIPS-related tests:
cargo test
No feature flag is required. FIPS tests load a LibCtx, load the fips and
base providers, and fetch algorithms from that isolated context. They call
fips::is_running at runtime and skip themselves if the FIPS provider is
not installed.
The fips-provider Feature
The fips-provider Cargo feature is only for code that implements a FIPS
provider from Rust — accessing OpenSSL’s internal provider vtable, PROV_CTX
helpers, and related non-public APIs. It is unrelated to running in FIPS mode.
Ordinary application code does not need this feature; fips::is_running() is
always available without it.
Building with fips-provider requires the OpenSSL source tree (not just the
development headers) because the feature accesses non-public headers such as
crypto/evp.h, prov/provider_ctx.h, and internal/provider.h:
export OPENSSL_SOURCE_DIR=/path/to/openssl-3.5.0
cargo build --features fips-provider
The build system runs a second bindgen pass against fips_wrapper.h (written
to $OUT_DIR) that includes these private headers with appropriate #define
guards. It also compiles a small C probe to determine the byte offset of
keydata inside evp_pkey_st for the current target ABI, writing the result
to $OUT_DIR/keydata_offset.rs and exposing it as
native_ossl_sys::fips_internal::EVP_PKEY_KEYDATA_OFFSET.
This feature is validated on 64-bit LP64 Linux targets (x86_64, aarch64, riscv64, s390x). 32-bit targets are not yet supported.
Version-Gated Features
Several APIs are conditionally compiled based on the installed OpenSSL version. The build system detects capabilities automatically — no manual flags are needed.
Version flags (from OPENSSL_VERSION_NUMBER):
| cfg flag | Minimum version | APIs enabled |
|---|---|---|
ossl307 | 3.0.7 (floor) | always active; baseline signal |
ossl310 | 3.1.0 | Clone for RandCtx |
ossl320 | 3.2.0 | MessageSigner, MessageVerifier, SigAlg, EncapCtx, DecapCtx, GlobalRandCtx, RandCtx::public/private_global, ErrState |
ossl350 | 3.5.0 | SshkdfBuilder, KbkdfBuilder and related types |
ossl_v400 | 4.0.0 | DigestCtx::serialize_size, DigestCtx::serialize, DigestCtx::deserialize |
Algorithm-presence flags (from header macros; absent when the algorithm family was not compiled into this OpenSSL installation):
| cfg flag | Meaning |
|---|---|
ossl_slhdsa | SLH-DSA algorithm family available |
ossl_mldsa | ML-DSA algorithm family available |
ossl_mlkem | ML-KEM algorithm family available |
param_clear_free | OSSL_PARAM_clear_free available (secure param cleanup) |
To inspect which flags are active for the current build:
cargo rustc -p native-ossl -- --print=cfg 2>&1 | grep ossl
Tests for version-gated features carry matching #[cfg(...)] attributes and are
automatically skipped when the flag is not set.
Integration Tests
Integration tests live in native-ossl/tests/:
tests/
├── test_digest.rs — SHA-2, SHA-3 NIST test vectors
├── test_cipher.rs — AES-GCM, ChaCha20-Poly1305 NIST vectors
├── test_mac.rs — HMAC, CMAC NIST vectors
├── test_pkey.rs — RSA, ECDSA, Ed25519 sign/verify round-trips
├── test_kdf.rs — HKDF, PBKDF2, scrypt test vectors
├── test_x509.rs — parse real certificates, verify self-signed
└── test_ssl.rs — in-process TLS with paired memory BIOs
Run them separately to reduce noise:
cargo test -p native-ossl --test test_digest
cargo test -p native-ossl --test test_ssl
The encrypt-demo Example
examples/encrypt-demo demonstrates hybrid encryption using RSA-OAEP + AES-256-GCM:
cargo run -p encrypt-demo
It exercises: key generation, public key serialization, RSA-OAEP encryption of a symmetric key, AES-256-GCM encryption of a payload, decryption and verification of the authentication tag, and round-trip assertion.
Documentation
Build the mdbook documentation locally:
# Install mdBook if not present
cargo install mdbook
# Build and open in browser
cd docs
mdbook build --open
# Serve with live reload during editing
mdbook serve
The built book is written to docs/book/ and is not committed to the repository.
Vendored OpenSSL Build
To build against a specific OpenSSL source tree rather than the system library:
# Point to the OpenSSL source tree
export KRYOPTIC_OPENSSL_SOURCES=/path/to/openssl-3.5.0 # or NATIVE_OSSL_OPENSSL_SOURCES
cargo build --features vendored
The vendored feature invokes the build_vendored() path in build.rs, which
runs ./Configure and make against the source tree and links the result
statically. This is useful for reproducible builds and CI environments without a
system OpenSSL installation.
Continuous Integration Checklist
A release-ready state requires:
cargo fmt --all --check # formatting
cargo clippy --all-targets -- -D warnings # lints
cargo test --all # tests (FIPS skipped if provider absent)
cargo doc --no-deps # documentation compiles
All of these must pass with zero warnings.