# FreeHSM C — Politique de sécurité non-propriétaire (candidat FIPS 140-3)

> English version: [`FIPS_140_3.md`](FIPS_140_3.md). In case of discrepancy, the English version prevails.

**Nom du module :** FreeHSM Cryptographic Module (libfreehsm.so)
**Version :** 1.0.0-FIPS
**Type :** logiciel, Niveau 1 (multi-puces autonome, lié à l'OS)
**Cible de validation :** FIPS 140-3 (ISO/IEC 19790:2012 + 24759:2017)
**Autorité de validation :** NIST CMVP (US) / CCCS (Canada)

---

## 1. Présentation du module

FreeHSM est un module cryptographique logiciel qui expose une interface PKCS#11 v3.2 aux applications. Il est destiné à servir de Soft HSM dans des environnements de production où un HSM matériel n'est pas disponible mais où la conformité FIPS 140-3 Niveau 1 est requise (PKI internes, serveurs de signature de code, charges SaaS régulées).

La *frontière cryptographique* est constituée du seul objet partagé `libfreehsm.so` plus le provider FIPS d'OpenSSL (`fips.so`) qu'il charge dynamiquement au `C_Initialize`. Tout le reste — application appelante, OS hôte, providers OpenSSL base/default — est hors frontière.

## 2. Frontière cryptographique

```
                  ┌─────────────────────────────────────────────┐
                  │     Application                             │
                  └──────────────────┬──────────────────────────┘
                                     │  ABI PKCS#11 v3.2 (C_*)
   ┌─── frontière ──────────────────┼─────────────────────────────┐
   │                                ▼                              │
   │         libfreehsm.so (ce module)                        │
   │            fhsm_pkcs11.c    — entry points (audit + dispatch) │
   │            fhsm_crypto.c    — KAT, AES-GCM, HMAC, PBKDF2      │
   │            fhsm_token.c     — token store, PIN, throttle      │
   │            fhsm_session.c   — table de sessions               │
   │            fhsm_audit.c     — log d'audit HMAC-chaîné         │
   │            fhsm_memory.c    — secure heap, zéroisation        │
   │            fhsm_state.c     — machine à états                 │
   │            fhsm_integrity.c — self-test d'intégrité au boot   │
   │                                ▼                              │
   │         Provider FIPS OpenSSL (fips.so)                       │
   └────────────────────────────────────────────────────────────────┘
```

## 3. Rôles, services, authentification

Le module supporte deux rôles d'opérateur :

| Rôle               | Identifiant PKCS#11 | Authentification |
|--------------------|---------------------|------------------|
| Crypto Officer (CO) | `CKU_SO`           | PBKDF2-HMAC-SHA-256 200 000 itérations |
| Utilisateur         | `CKU_USER`         | PBKDF2-HMAC-SHA-256 200 000 itérations |

L'authentification est par slot. Les PIN doivent comporter au moins 8 caractères. Après `FHSM_PIN_MAX_FAILED = 5` échecs consécutifs, le rôle est verrouillé (`FHSM_RV_PIN_LOCKED`) ; seul `C_InitPIN` (pour USER, appelé par SO) ou `C_InitToken` (pour les deux) libère le verrou.

Entre tentatives échouées, le module applique un *backoff* exponentiel : `delay_n = min(500 ms × 2^(n-1), 60 s)`. Le throttle est persisté dans le fichier token : un redémarrage du processus ne le contourne pas.

### 3.1 Cartographie des services

| Service                  | Rôles autorisés | Approuvé ? | Mode FIPS ? |
|--------------------------|-----------------|------------|-------------|
| `C_Initialize`           | (aucun)         | n/a        | oui         |
| `C_GetInfo`              | (aucun)         | n/a        | oui         |
| `C_Login`                | CO, USER        | n/a        | oui         |
| `C_GenerateKey`          | CO, USER        | oui        | oui         |
| `C_Encrypt` (AES-GCM)    | USER            | oui        | oui         |
| `C_Decrypt` (AES-GCM)    | USER            | oui        | oui         |
| `C_Sign` (RSA-PSS, ECDSA, EdDSA, ML-DSA) | USER | oui | oui |
| `C_Verify` (idem)        | USER            | oui        | oui         |
| `C_Digest` (SHA-2, SHA-3)| (aucun)         | oui        | oui         |
| `C_DeriveKey` (HKDF, PBKDF2) | USER        | oui        | oui         |
| `C_EncapsulateKey` (ML-KEM)  | USER        | oui        | oui         |
| `C_DecapsulateKey` (ML-KEM)  | USER        | oui        | oui         |
| `C_Sign` (MD5, SHA-1, DSA, RSA-PKCS1-v1.5) | --- | **non** | rejeté |

Les services marqués **non approuvés** retournent `FHSM_RV_FIPS_NOT_APPROVED` quand `FHSM_FIPS_ONLY = 1`. Ils restent dispatchables dans les builds non approuvés pour l'interopérabilité avec des systèmes hérités ; la transition entre/hors mode approuvé est signalée dans le log d'audit (événement `state_transition`).

## 4. Algorithmes approuvés

| Famille       | Variante / paramètres                 | Référence     | Cert. CAVP   |
|---------------|---------------------------------------|---------------|--------------|
| AES           | 128 / 192 / 256-GCM, CBC, KW, KWP     | FIPS 197 / SP 800-38{A,D,F} | TBD |
| SHA-2         | SHA-256, SHA-384, SHA-512             | FIPS 180-4    | TBD          |
| SHA-3         | SHA3-256/384/512, SHAKE128/256        | FIPS 202      | TBD          |
| HMAC          | avec toutes les SHA-2/3 approuvées    | FIPS 198-1    | TBD          |
| KMAC          | KMAC128, KMAC256                      | SP 800-185    | TBD          |
| RSA-PSS       | 2048, 3072, 4096                      | FIPS 186-5    | TBD          |
| ECDSA         | P-256, P-384, P-521                   | FIPS 186-5    | TBD          |
| EdDSA         | Ed25519, Ed448                        | FIPS 186-5    | TBD          |
| ECDH/X25519/X448 | P-256, P-384, X25519, X448         | SP 800-56A    | TBD          |
| ML-KEM        | 512 / 768 / 1024                      | FIPS 203      | TBD          |
| ML-DSA        | 44 / 65 / 87                          | FIPS 204      | TBD          |
| SLH-DSA       | SHA2/SHAKE × 128/192/256 × s/f        | FIPS 205      | TBD          |
| HKDF          | avec SHA-256/384/512                  | SP 800-56C    | TBD          |
| PBKDF2        | HMAC-SHA-256, ≥ 200 000 itér.         | SP 800-132    | TBD          |
| CTR_DRBG      | AES-256, derivation function          | SP 800-90A    | TBD          |
| Source d'entropie | Linux `getrandom(GRND_RANDOM)`    | SP 800-90B    | ESV TBD      |

## 5. Paramètres de sécurité sensibles (SSP)

Tous les SSP sont stockés **exclusivement dans le secure heap OpenSSL** (`OPENSSL_secure_malloc`), une unique arène `mlock`-ée. La taille de l'arène est configurable au build (par défaut 256 KiB). Les allocations sont rendues via `OPENSSL_secure_clear_free`, qui zéroise avant libération.

| SSP                      | Algorithme              | Stockage              | Déclencheur de zéroisation |
|--------------------------|-------------------------|-----------------------|----------------------------|
| DEK                      | AES-256                 | Secure heap (vivante) | `C_Logout`, `C_Finalize`, lock |
| KEK dérivées du PIN      | AES-256                 | Secure heap (vivante) | Après écriture du token   |
| Clés privées (RSA, EC, PQ) | RSA 2048-4096, EC, PQ | Secure heap (vivante) | `C_DestroyObject`, logout  |
| Clé MAC d'audit          | HMAC-SHA-256            | Secure heap (vivante) | `C_Finalize`               |
| Plaintexts KAT           | (cf. §6)                | Secure heap (transit) | Fin du KAT                 |
| État DRBG                | CTR_DRBG                | Provider FIPS OpenSSL | Déchargement du provider   |

## 6. Auto-tests

### 6.1 Auto-tests pré-opérationnels (FIPS 140-3 §7.10.2)

Exécutés au `C_Initialize`, avant qu'aucun service ne devienne disponible :

1. **Test d'intégrité logicielle** (§7.10.2.a) : SHA-256 du `libfreehsm.so` calculé puis comparé à la valeur embarquée au build dans `fhsm_module_integrity_digest[]`. Mismatch → état ERROR.
2. **Initialisation du DRBG durci** : `fhsm_drbg_init` exécute le seed multi-source (`getrandom + RDRAND + /dev/urandom + jitter TSC` → conditionneur SHA-256 → `RAND_add`). Source indisponible → ERROR. Voir [`RNG.md`](RNG.md) pour le pipeline.
3. **Auto-test des algorithmes cryptographiques (KAT)** : chaque primitive approuvée (§4) exécutée contre un vecteur CAVP. Set de base dans `kat/fhsm_kat_vectors.c` ; **v1.1.0 ajoute** un set CAVP étendu dans `kat/cavp_extended.c` (2 AES-GCM-256 du NIST SP 800-38D Annex B + 4 HMAC-SHA-256 du RFC 4231). Tout mismatch → ERROR.

### 6.2 Auto-tests conditionnels (§7.10.3)

| Déclencheur | Test | Implémentation |
|---|---|---|
| Déchiffrement AEAD | Vérification du tag (constant-time) | `fhsm_aes_gcm_decrypt` rejette sur mismatch |
| Vérification de signature | Vérification spécifique à l'algo | Inline dans `C_Verify` |
| **Génération de paire asymétrique (§7.10.2.b)** | **Pair-wise consistency check** : aller-retour chiffre-déchiffre (RSA), sign-verify (EC, ML-DSA, SLH-DSA), encap-decap (ML-KEM). Échec → ERROR latché + refus de persister la clé. | `src/fhsm_pairwise.c`, invoqué inline par `C_GenerateKeyPair` |
| **Sortie du RNG (§7.10.3.b)** | **Test continu** : RCT (cutoff 6 octets identiques consécutifs) + APT (W=512, cutoff 51) + CRNGT (bloc 16 octets comparé entre appels). | `src/fhsm_drbg.c` `health_rct_apt` + `health_crngt` |

## 7. Environnement opérationnel

Le module est validé pour l'environnement opérationnel suivant :

- OS : Linux ≥ 5.4 avec autorisation `mlock` et `RLIMIT_MEMLOCK` ≥ 1 MiB
- libc : glibc ≥ 2.31 ou musl ≥ 1.2
- OpenSSL : 3.x avec provider FIPS installé et listé dans `openssl.cnf`
- Filesystem : ext4 ou xfs pour le log d'audit (sémantique `append` atomique)

Les opérateurs doivent :
1. S'assurer que le provider FIPS OpenSSL est chargé et validé (`openssl list -providers` montre `fips` en statut `active`).
2. Stocker les fichiers token (`*.tok`) et d'audit (`*.audit.log`) sur un FS non monté en réseau (NFS/CIFS peuvent perdre l'atomicité).
3. Exécuter le module sous un utilisateur UNIX dédié avec `CAP_IPC_LOCK` pour autoriser le `mlock` du secure heap.

## 8. Atténuations d'attaques diverses

| Attaque                     | Atténuation                                       |
|-----------------------------|---------------------------------------------------|
| Canaux temporels sur PIN    | Throttle appliqué *avant* PBKDF2 ; compare constant-time |
| Exfiltration cold-boot DEK  | Secure heap mlock + zéroisation au free          |
| Fuite par coredump          | `prctl(PR_SET_DUMPABLE, 0)` au C_Initialize       |
| Injection dans le log       | L'émission d'audit refuse tout octet hors `[0x20, 0x7e]` et `[",\\]` |
| Altération de l'audit       | Log HMAC-chaîné + clé MAC dérivée du token        |
| Brute-force sur PIN         | Backoff exponentiel + verrou à 5 échecs           |
| Épuisement de seed DRBG     | Seuils de réamorçage SP 800-90A + point d'entrée reseed |
