Skip to content

Commit 25def97

Browse files
committed
Document libsodium hardening and simplify API surface
1 parent d268766 commit 25def97

File tree

4 files changed

+99
-17
lines changed

4 files changed

+99
-17
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ git submodule add https://github.com/SWORDIntel/IMAGEHARDER.git external/imageha
1818
```
1919

2020
## Public API (library)
21-
Add the crate to your workspace and call the unified API surface:
21+
Add the crate to your workspace and call the hardened helpers directly:
2222

2323
```toml
2424
# parent-project/Cargo.toml
@@ -27,10 +27,10 @@ image_harden = { path = "external/imageharder/image_harden" }
2727
```
2828

2929
```rust
30-
use image_harden::api::{DecodedMedia, HardenedDecoder, MediaFormat};
30+
use image_harden::decode_png;
3131

32-
fn decode(bytes: &[u8]) -> Result<DecodedMedia, image_harden::ImageHardenError> {
33-
HardenedDecoder::decode(MediaFormat::Png, bytes)
32+
fn decode(bytes: &[u8]) -> Result<Vec<u8>, image_harden::ImageHardenError> {
33+
decode_png(bytes)
3434
}
3535
```
3636

@@ -46,6 +46,7 @@ cargo build --release
4646
- `image_harden/` – Rust crate with the hardened decoders and CLI entrypoint.
4747
- `docs/INTEGRATION.md` – concise guide for embedding as a submodule.
4848
- `docs/archive/` – preserved deep-dives (build notes, platform guides, extended hardening writeups).
49+
- `docs/HARDENING_LIBSODIUM.md` – exploratory notes on applying similar hardening patterns to libsodium.
4950
- `config/`, `ffmpeg/`, `docker-compose.yml` – deployment aids retained for downstream integrators.
5051

5152
## Security

docs/HARDENING_LIBSODIUM.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Applying IMAGEHARDER-style hardening to libsodium
2+
3+
The same practices used in IMAGEHARDER (bounded inputs, explicit error mapping, metrics, and sandboxing) can be mirrored when embedding
4+
[libsodium](https://github.com/jedisct1/libsodium) for cryptographic workloads. This note outlines a secure-integration profile
5+
suitable for Xen domU/CI builders.
6+
7+
## Goals
8+
- Stable, minimal FFI boundary with explicit error types.
9+
- Deterministic builds that pin versions and compiler flags.
10+
- Isolation of key material and misuse-resistant APIs.
11+
- Observability: metrics, tamper-evident audit logs, and build provenance.
12+
13+
## Build strategy
14+
- **Version pinning**: vendor a known-good libsodium release and verify with `sha256sum` before build.
15+
- **Compiler flags**: prefer `-fstack-protector-strong -D_FORTIFY_SOURCE=3 -fPIC -O2 -pipe -fno-plt` plus
16+
`-fstack-clash-protection` on supported toolchains. Enable `-fcf-protection=full` for CET-capable targets.
17+
- **Linking**: prefer static linking in minimal domU images; use `RUSTFLAGS="-C target-feature=+crt-static"` when pairing with
18+
Rust consumers to avoid dynamic search-path issues.
19+
- **Reproducibility**: capture build metadata (compiler, flags, git SHA) in an SBOM; wire `generate-sbom.sh` as part of CI.
20+
21+
## FFI surface design
22+
- Wrap each libsodium primitive in narrow functions that accept length-checked slices and return `Result<Output, CryptoError>`.
23+
- Prohibit raw pointer exposure; translate C error codes into typed Rust errors with context.
24+
- Add zeroization hooks (`zeroize::Zeroize`) for buffers that carry keys, nonces, or secrets.
25+
- Enforce domain separation by tagging APIs per purpose (e.g., `Auth`, `Aead`, `Kdf`) to discourage misuse.
26+
27+
## Runtime safeguards
28+
- **Initialization guard**: perform a one-time `sodium_init()` with failure handling before exposing any primitive.
29+
- **Key lifecycle**: keep keys in guarded memory (e.g., `secrecy::SecretVec`) and avoid serialization. Provide key-generation
30+
helpers that default to high-entropy RNGs (libsodium already defaults to `randombytes_buf`), and expose optional hardware RNG
31+
seeding for dom0/domU if available.
32+
- **Parameter validation**: validate nonce sizes, tag lengths, and buffer boundaries before calling into libsodium.
33+
- **Constant-time expectations**: document which APIs are constant-time and block callers from using them for unrelated purposes
34+
(e.g., no generic equality on MACs without constant-time compare).
35+
36+
## Observability and policy
37+
- Emit Prometheus counters for successes/failures per primitive (without leaking secrets) and gauge unexpected parameter
38+
rejections.
39+
- Capture audit logs that include operation type, key identifier, and policy decisions; ship logs over mTLS to central storage.
40+
- Include a policy module that enforces approved cipher suites (e.g., `xchacha20poly1305_ietf`) and blocks deprecated ones.
41+
42+
## Testing and validation
43+
- **KATs**: integrate libsodium's known-answer tests and add fuzzers around the FFI boundary to catch length/parameter issues.
44+
- **Memory checks**: run under `valgrind`/`ASan` in CI; ensure zeroization paths are covered.
45+
- **Cross-platform**: validate builds under Xen domU, containers, and bare-metal to confirm consistent instruction sets and
46+
`RDRAND` availability.
47+
48+
## Example integration sketch
49+
50+
```rust
51+
// Pseudocode illustrating a narrow AEAD wrapper
52+
pub fn seal(key: &SecretVec<u8>, nonce: &[u8; crypto_aead_xchacha20poly1305_ietf_NPUBBYTES],
53+
aad: &[u8], plaintext: &[u8]) -> Result<Vec<u8>, CryptoError> {
54+
if plaintext.len() > MAX_MESSAGE || aad.len() > MAX_AAD {
55+
return Err(CryptoError::InputTooLarge);
56+
}
57+
58+
let mut ciphertext = vec![0u8; plaintext.len() + TAG_LEN];
59+
let mut clen = 0usize;
60+
let rc = unsafe {
61+
crypto_aead_xchacha20poly1305_ietf_encrypt(
62+
ciphertext.as_mut_ptr(),
63+
&mut clen,
64+
plaintext.as_ptr(),
65+
plaintext.len() as u64,
66+
aad.as_ptr(),
67+
aad.len() as u64,
68+
std::ptr::null(),
69+
nonce.as_ptr(),
70+
key.expose_secret().as_ptr(),
71+
)
72+
};
73+
74+
if rc != 0 {
75+
return Err(CryptoError::EncryptionFailed);
76+
}
77+
78+
ciphertext.truncate(clen);
79+
Ok(ciphertext)
80+
}
81+
```
82+
83+
## Operational checklist
84+
- Verify SBOM provenance for each release and store alongside build artifacts.
85+
- Rotate keys on a fixed schedule; enforce non-reuse of nonces via per-key counters.
86+
- Run `cargo deny` (or equivalent) to flag transitive CVEs in Rust bindings.
87+
- Add a chaos test that simulates allocator failures to ensure safe unwinding.
88+
89+
Following this pattern mirrors IMAGEHARDER's focus on bounded inputs, explicit error handling, and strong observability—adapted to the
90+
cryptographic domain served by libsodium.

docs/INTEGRATION.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,16 @@ members = [
2727
```
2828

2929
## 3) Call the public API
30-
The `api` module exposes a minimal surface that wraps the internal decoders and feature-gated formats.
30+
Use the hardened helpers directly. Each decoder returns either raw bytes (images/video) or `AudioData` for audio formats.
3131

3232
```rust
33-
use image_harden::api::{DecodedMedia, HardenedDecoder, MediaFormat};
33+
use image_harden::decode_png;
3434

35-
fn decode_png(bytes: &[u8]) -> Result<DecodedMedia, image_harden::ImageHardenError> {
36-
HardenedDecoder::decode(MediaFormat::Png, bytes)
35+
fn decode_png(bytes: &[u8]) -> Result<Vec<u8>, image_harden::ImageHardenError> {
36+
decode_png(bytes)
3737
}
3838
```
3939

40-
You can check what is currently compiled in (based on enabled features) at runtime:
41-
```rust
42-
let advertised = image_harden::api::supported_formats();
43-
assert!(advertised.contains(&"png"));
44-
```
45-
4640
## 4) Feature flags
4741
Optional formats are disabled by default to keep builds lean. Enable only what you need in the dependency declaration:
4842

image_harden/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ use thiserror::Error;
1414
pub mod metrics;
1515
pub mod metrics_server;
1616

17-
// Public API surface
18-
pub mod api;
19-
2017
// Extended format support
2118
pub mod formats;
2219

0 commit comments

Comments
 (0)