FreeHSM C

An open-source PKCS#11 v3.2 cryptographic module under Simorgh Labs

View the Project on GitHub afchine1337/freehsm

FreeHSM C — Politique de sécurité non-propriétaire (méthode FIPS 140-3 niveau 1, non certifié)

English version: 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 ; SHA-1 en HMAC seulement FIPS 198-1, SP 800-131A rev. 2 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 toutes les SHA-2/3 approuvées ; SHA-1 comme PRF SP 800-56C rev. 2 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

SHA-1, et pourquoi il figure dans deux lignes ci-dessus et dans aucune des lignes de signature. SP 800-131A rev. 2 limite l’interdiction de SHA-1 à la génération de signatures. Il reste acceptable à l’intérieur de HMAC, et donc à l’intérieur des KDF fondées sur HMAC de SP 800-56C rev. 2. Le module suit cette frontière plutôt qu’une règle globale : CKM_SHA_1_HMAC et CKM_HKDF_DERIVE avec prfHashMechanism = CKM_SHA_1 sont acceptés en fips-strict, tandis que C_Digest(CKM_SHA_1) et CKM_SHA1_RSA_PKCS y sont refusés.

Jusqu’au 19/09/2026 le code ne traçait pas cette frontière. Un seul drapeau marquait SHA-1 non approuvé pour tout usage, si bien que HMAC-SHA-1 était approuvé par C_SignInit et refusé par le PRF de HKDF — une primitive, deux chemins, deux réponses. L’échec était fermé, donc sans coût de sécurité ; il a coûté les 84 vecteurs valides de hkdf_sha1_test.json et une explication à chaque lecture du rapport. Ce tableau disait SHA-2/3 seulement, et docs/MECHANISMS.md, qui est généré à partir du profil, disait CKM_SHA_1_HMAC approuvé. Les deux se contredisaient sur la même primitive. C’est le document généré qui avait raison.

Les cellules TBD seront renseignées lorsque la file d’attente CMVP avancera et que le laboratoire exécutera ACVP. Le jeu complet de vecteurs CAVP est chargé à l’initialisation du module par fhsm_kat_run_all (voir §6).

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 mmap verrouillée par mlock. Sa taille est fixée au build (8 MiB par défaut, configurable par FHSM_SECURE_HEAP_BYTES ou par le réglage secure_heap_kb) et elle contient toute valeur d’objet sensible, non seulement les DEK (#127). Les allocations sont rendues via OPENSSL_secure_clear_free, qui zéroise le bloc 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-384 → RAND_add). Source indisponible → ERROR. Voir 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 :

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