# FreeHSM --- FIPS 140-3 / CC EAL4+ discipline, without the certificate

[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![REUSE status](https://api.reuse.software/badge/github.com/afchine1337/freehsm)](https://api.reuse.software/info/github.com/afchine1337/freehsm)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/13190/badge)](https://www.bestpractices.dev/projects/13190)
[![CI](https://github.com/afchine1337/freehsm/actions/workflows/ci.yml/badge.svg)](https://github.com/afchine1337/freehsm/actions/workflows/ci.yml)
[![Mirror](https://github.com/afchine1337/freehsm/actions/workflows/mirror.yml/badge.svg)](https://github.com/afchine1337/freehsm/actions/workflows/mirror.yml)

> French version: see [`README.fr.md`](README.fr.md). Documentation index: [`docs/DOC_INDEX.md`](docs/DOC_INDEX.md).
>
> **FreeHSM** is the open-source PKCS#11 library, stewarded by **[Simorgh Labs](https://chaharsou.com)**. PKI and signing tooling on top of it is planned, not built. *(Repository renamed from `freehsm-c` to `freehsm` in July 2026; old URLs redirect.)*

Native **C11** re-implementation of the FreeHSM PKCS#11 v3.2 Soft HSM, designed to pass a FIPS 140-3 Level 1 evaluation and an augmented Common Criteria EAL4+ certification (ALC_FLR.2 + AVA_VAN.5).

## Why C ?

The Python POC is functionally complete (165 passing tests, façade + engine + store + CFFI binding + TPM/KMS sealing + PQ FIPS 203/204/205 coverage), but Python is not evaluable :

- The interpreter is inside the module boundary, which becomes unmanageable.
- The Python allocator is garbage-collected --- no zeroization guarantee.
- The crypto primitives delegate to `cryptography` (CFFI → libssl), adding an untraceable boundary.

The C port removes these obstacles : a single `.so` (`libfreehsm.so`) directly loading the **OpenSSL 3.x FIPS provider** (separately validated), with a `mlock()`-ed *secure heap* for all SSP, and a boundary made exclusively of the `C_*` PKCS#11 symbols.

## Structure

```
freehsm/
├── Makefile                       # Hardened build + reproducibility + lint + generate
├── Dockerfile.build               # Pinned image for reproducible builds (Debian 12 + OpenSSL FIPS)
├── include/
│   ├── fhsm_common.h              # Types, return codes, state machine, roles
│   ├── fhsm_crypto.h              # FIPS-approved primitives (AES-GCM, HMAC, PBKDF2, DRBG)
│   ├── fhsm_token.h               # Token store, throttle, lockout
│   ├── fhsm_audit.h               # HMAC-chained audit log
│   ├── fhsm_integrity.h           # Boot integrity self-test (FIPS 140-3 §7.10.2)
│   └── fhsm_pkcs11_mechanisms.h   # [GENERATED] CKM_* + handler signature + table
├── src/
│   ├── fhsm_state.c               # State machine (FIPS 140-3 §7.4.2)
│   ├── fhsm_memory.c              # Secure heap (OpenSSL OPENSSL_secure_malloc)
│   ├── fhsm_crypto.c              # EVP wrappers + KAT runner
│   ├── fhsm_audit.c               # Append-only HMAC-chained log
│   ├── fhsm_token.c               # Slot persistence + PIN throttle
│   ├── fhsm_session.c             # Session table
│   ├── fhsm_pkcs11.c              # C_* entry points (TSFI)
│   ├── fhsm_integrity.c           # Boot self-test : .fhsm_digest section + SHA-256
│   ├── gen/
│   │   └── fhsm_dispatch.c        # [GENERATED] Dispatch table for 78 CKM_* + weak stubs
│   └── dispatch/                  # Concrete handlers per family (66 approved)
│       ├── fhsm_dispatch_digest.c # SHA-2/3, SHAKE128/256
│       ├── fhsm_dispatch_hmac.c   # HMAC-SHA-2/3
│       ├── fhsm_dispatch_aes.c    # AES-GCM/CBC/CTR/CCM/KW/KWP/CMAC
│       ├── fhsm_dispatch_kdf.c    # PBKDF2, HKDF, NIST PRF KDF
│       ├── fhsm_dispatch_pkey.c   # RSA-PSS/OAEP, ECDSA, EdDSA, ECDH
│       ├── fhsm_dispatch_pq.c     # ML-KEM/DSA, SLH-DSA (provider-aware)
│       ├── fhsm_dispatch_kmac.c   # KMAC128/256 (SP 800-185)
│       ├── fhsm_dispatch_concat.c # CONCATENATE_*, XOR_BASE_AND_DATA
│       └── fhsm_dispatch_hybrid.c # Hybrid PQ + classical KEM and signature
├── scripts/
│   ├── gen_p11_thunks.py          # Single source of truth for the dispatch (mechanism db)
│   ├── sign_module.sh             # Patches the SHA-256 digest into .fhsm_digest
│   ├── build_reproducible.sh      # Builds inside pinned Docker (out/digest.txt)
│   └── verify_reproducibility.sh  # Builds twice, asserts identical SHA-256
├── kat/
│   ├── fhsm_kat_rsp.{h,c}         # CAVP .rsp parser + 6 per-algorithm runners
│   ├── fhsm_kat_vectors.c         # In-binary vectors (boot self-test)
│   └── cavp/                      # 83 CAVP vectors (.rsp) cross-validated against Python
├── tests/
│   ├── test_smoke.c               # E2E smoke (init + KAT + encrypt/decrypt + tamper)
│   └── test_dispatch.c            # Checks weak/strong override, table sort, counts
└── docs/
    ├── DOC_INDEX.md               # Bilingual doc index
    ├── ARCHITECTURE.md            # Modular decomposition + data flow
    ├── FIPS_140_3.md              # Non-proprietary Security Policy (FIPS 140-3)
    ├── EAL4_PLUS.md               # Target of Evaluation (CC EAL4+)
    ├── MECHANISMS.md              # [GENERATED] Dispatch reference (78 CKM_*)
    ├── REPRODUCIBLE_BUILD.md      # Bit-identical build procedure
    ├── ATE_FUN.md                 # Functional Test (ATE_FUN.1 + COV.2 + DPT.1)
    ├── AVA_VAN.md                 # Vulnerability Analysis (AVA_VAN.5)
    ├── ALC_CMC.md                 # Configuration Management (ALC_CMC.4)
    ├── AGD_PRE.md                 # Preparative Procedures (admin install guide)
    └── AGD_OPE.md                 # Operational Guidance (operator manual)
```

## Build

```bash
# Prerequisites : OpenSSL 3.x with the FIPS provider
sudo apt install -y libssl-dev cmake ninja-build
# (If the FIPS provider is not pre-installed, build it from OpenSSL sources with
#  ./Configure enable-fips && make install_fips.)

make generate                  # regenerate the mechanism dispatch (CKM_* + table + doc)
make generate PROFILE=interop  # same but with legacy CKM_* dispatchable (audit-only)
make                           # generate then build libfreehsm.so
make tests                     # run test_smoke (POST + KAT + AES-GCM RT + tamper)
make integrity                 # patch SHA-256 into fhsm_module_integrity_digest[]
make repro                     # build inside the pinned Docker image
make dist-verify               # build twice, assert byte-identical SHA-256
make dist                      # reproducible source tar.xz for the evaluator
```

## Mechanism dispatch (78 `CKM_*`)

The module supports **66 FIPS-approved** mechanisms and **12 legacy** ones (rejected by default in `fips-strict` profile, audited in `interop`). The dispatch table is not hand-written : it is generated from a **single source of truth** (`scripts/gen_p11_thunks.py`), which lets an evaluator diff this one file against §4 of the Security Policy to verify exhaustiveness.

| Family            | Approved | Mechanisms |
|-------------------|----------|------------|
| AES               | 9        | `KEY_GEN`, `CBC`, `CBC_PAD`, `GCM`, `CCM`, `CTR`, `KEY_WRAP`, `KWP`, `CMAC` |
| SHA-2             | 6        | `SHA224/256/384/512`, `SHA512_224/256` |
| SHA-3 / SHAKE     | 5        | `SHA3_256/384/512`, `SHAKE128/256` |
| HMAC              | 6        | SHA-2-{256,384,512} + SHA-3-{256,384,512} |
| **KMAC**          | **2**    | **`KMAC128`, `KMAC256`** (SP 800-185) |
| RSA               | 6        | `KEY_PAIR_GEN`, `PSS` (+ `SHA256/384/512`), `OAEP` |
| EC (NIST)         | 7        | `KEY_PAIR_GEN`, `ECDSA` (+ 3 SHA), `ECDH1`, `ECDH1_COFACTOR` |
| EdDSA / X25519/X448 | 5      | `EC_EDWARDS_KEY_PAIR_GEN`, `EDDSA`, `EC_MONTGOMERY_KEY_PAIR_GEN`, `X25519_DERIVE`, `X448_DERIVE` |
| ML-KEM (FIPS 203) | 2        | `ML_KEM_KEY_PAIR_GEN`, `ML_KEM` |
| ML-DSA (FIPS 204) | 4        | `KEY_PAIR_GEN`, `ML_DSA`, `HASH_ML_DSA_SHA256/512` |
| SLH-DSA (FIPS 205)| 2        | `SLH_DSA_KEY_PAIR_GEN`, `SLH_DSA` |
| **Hybrid PQ**     | **2**    | **`HYBRID_X25519_ML_KEM_768`** (KEM), **`HYBRID_ED25519_ML_DSA_65`** (signature) |
| HKDF              | 3        | `DERIVE`, `DATA`, `KEY_GEN` |
| PBKDF2 / KDF      | 2        | `PKCS5_PBKD2` (200 000 iter min), `NIST_PRF_KDF` |
| **Concat KDF**    | **4**    | **`CONCATENATE_BASE_AND_KEY/DATA`, `CONCATENATE_DATA_AND_BASE`, `XOR_BASE_AND_DATA`** |
| Generic           | 1        | `GENERIC_SECRET_KEY_GEN` |
| **Legacy rejected** | **12** | `AES_ECB`, `RSA_PKCS`, `RSA_X_509`, `SHA1_RSA_PKCS`, `MD5`, `SHA_1`, `DES_KEY_GEN`, `DES3_KEY_GEN`, `DES3_CBC`, `RC4`, `DH_PKCS_KEY_PAIR_GEN`, `DSA_KEY_PAIR_GEN` |

## Evaluation status

| Step                                          | Status | Evidence |
|-----------------------------------------------|--------|----------|
| Strict C11 source                             | ✅     | `Makefile` (`-Werror -Wpedantic`) |
| Single cryptographic boundary                 | ✅     | `docs/FIPS_140_3.md` §2 |
| mlock-ed secure heap for SSPs                 | ✅     | `src/fhsm_memory.c` |
| FIPS 140-3 §7.4.2 state machine               | ✅     | `src/fhsm_state.c` |
| Boot KAT (AES-GCM, SHA, HMAC, DRBG)           | ✅     | `kat/fhsm_kat_vectors.c` |
| **Boot integrity** (SHA-256 of .so)           | ✅     | `src/fhsm_integrity.c` + `scripts/sign_module.sh` |
| HMAC-chained audit log                        | ✅     | `src/fhsm_audit.c` |
| Algorithms restricted to approved set         | ✅     | `FHSM_FIPS_ONLY = 1` default |
| Exponential PIN throttle + lockout            | ✅     | `src/fhsm_token.c` |
| **Full dispatch (78 `CKM_*`)**                | ✅     | `scripts/gen_p11_thunks.py` + `src/gen/` |
| Non-proprietary Security Policy               | ✅     | `docs/FIPS_140_3.md` |
| CC EAL4+ Target of Evaluation                 | ✅     | `docs/EAL4_PLUS.md` |
| Auto-generated mechanism reference            | ✅     | `docs/MECHANISMS.md` |
| **Concrete handlers** (66 approved)           | ✅     | `src/dispatch/` 10 files, ~2 400 l. |
| **KMAC + concat KDF + PQ hybrids**            | ✅     | `dispatch_{kmac,concat,hybrid}*.c` |
| **CAVP `.rsp` parser + 83 vectors**           | ✅     | `kat/fhsm_kat_rsp.c` + `kat/cavp/` |
| Full CAVP set (100+/algo)                     | 🟡     | infrastructure ready, set to download |
| **Reproducible build** (pinned Dockerfile)    | ✅     | `Dockerfile.build` + `make dist-verify` |
| **Complete CC EAL4+ docs** (ATE/AVA/ALC/AGD)  | ✅     | 10 documents in `docs/` |
| Fuzzing tests + coverage ≥ 95 %               | ⏳     | infra to wire (AFL++ + lcov) |
| Validated OpenSSL FIPS provider               | n/a    | deployment choice; the module runs against whichever provider the operator installs |
| Third-party code audit (CC lab)               | ⏳     | commercial step |
| CMVP / CC lab submission                      | n/a    | not planned — see the note on certification below |

Legend : ✅ implemented · 🟡 partial/scaffold · ⏳ to do

## Synthesis

- **Strict C11** hardened (`-Werror -Wpedantic -fstack-protector-strong ...`), single cryptographic boundary (`libfreehsm.so` + OpenSSL 3.x FIPS provider).
- **78 `CKM_*`** dispatchable (66 FIPS-approved + 12 legacy rejected), generated from a single auditable source of truth.
- **66 concrete handlers** in `src/dispatch/` (10 files, ~2 400 l.), including KMAC, CONCATENATE/XOR KDFs, and 2 hybrid PQ + classical mechanisms.
- **Boot self-test FIPS 140-3 §7.10.2** : `.fhsm_digest` ELF section patched post-build, SHA-256 of the .so (digest area zeroized) verified before the FIPS provider loads.
- **Reproducible build** : `Dockerfile.build` pinned by digest. `make dist-verify` builds twice and asserts identical SHA-256.
- **CAVP `.rsp` parser** + **83 sample vectors** Python cross-validated.
- **10 evaluation documents** covering what a full CC EAL4+ / FIPS 140-3 dossier contains (Security Policy, TOE, Architecture, Mechanisms, Reproducible Build, ATE_FUN, AVA_VAN, ALC_CMC, AGD_PRE, AGD_OPE) — written to the methodologies and published as worked examples, not submitted anywhere.
- **~ 8 000 lines** of C + Python + Markdown across 40+ files.
- **Certification.** FreeHSM holds no certificate and is not seeking one. A CMVP or CC submission costs more than this project will ever have, and that cost is exactly the barrier that keeps public bodies, universities and developing countries away from auditable cryptography. The ten evaluation documents are published as worked examples of how such a module is specified and tested — material that is otherwise hard to find outside a paid engagement. What a certificate attests, discipline can make verifiable: by anyone, at no cost.

---

## Maintainer & brand

**Simorgh Labs — Open Source Cryptography and Digital Trust** — sponsoring entity for the FreeHSM project and publisher of **Simorgh PKI** (v2.0, in development: `fhsm-ca` PKI CLI + `fhsm-sign` signing toolkit + PQC composite signatures per IETF LAMPS). Maintained by Afchine Madjlessi (`afchine.mad@gmail.com`). All releases are GPG-signed with key `743A 6A59 04A1 4616 46A6 408D E485 6016 2DBB F28A 2` (Ed25519, unchanged across the rebrand). The PKCS#11 module reports `manufacturerID = "Simorgh Labs"` (truncated to the 32-octet field per PKCS#11 v3.2 §C.6.1). The library binary name `libfreehsm.so` and all PKCS#11 identifiers are stable — the rebrand changes no consumer-facing interface. Name and logo usage: see [`TRADEMARK.md`](TRADEMARK.md).
