
Libreria Zig per modulo di sicurezza hardware per token PIV, CAC e YubiKey tramite PC/SC. Supporta certificati, gestione PIN, firma e decifratura.
Una libreria Hardware Security Module (HSM) per Zig che fornisce accesso PC/SC a token PIV, CAC e YubiKey.
| Aspetto | Informazioni |
|---|---|
| Stabilità API | Sviluppo |
| Versione Zig | 0.16.0 |
| Piattaforme | Linux, macOS, Windows |
| Licenza | MIT |
Supporto PIV (NIST SP 800-73-4)
Supporto CAC (Common Access Card)
Supporto YubiKey
Sicurezza
anyerror)Operazioni parallele (tramite thread_pool)
-Denable_tp=true); disabilitare con -Denable_tp=falselibpcsclite-dev (Debian/Ubuntu) o pcsc-lite-devel (Fedora)# Debian/Ubuntu
sudo apt-get install libpcsclite-dev pcscd
# Fedora/RHEL
sudo dnf install pcsc-lite-devel pcsc-lite
# Start the PC/SC daemon
sudo systemctl start pcscd
sudo systemctl enable pcscd
# Build and run unit tests
make
# Or using zig directly
zig build test
# Run simulator integration tests
zig build test -Dintegration_sim=true
# Build examples (requires PC/SC library installed)
zig build examples -Dlink_pcsc=true
| Opzione | Predefinito | Descrizione | Impatto sulla sicurezza |
|---|---|---|---|
integration_sim | false | Esegui test di integrazione con simulatore | Nessuno |
hsm_hil | false | Esegui test hardware-in-loop (richiede token reale) | Nessuno |
link_pcsc | false | Collega libreria PC/SC per esempi | Nessuno |
include_simulator | Debug: trueRelease: false | Includi simulatore PIV con chiavi di test | CWE-321: Chiavi di test in produzione |
allow_pcsc_env_override | false | RISCHIO PER LA SICUREZZA: consenti variabile d'ambiente HSM_PCSC_LIB_PATH | CWE-427: Caricamento libreria non fidato |
fips | false | Instrada crittografia di sicurezza attraverso il provider FIPS-140-3 collegato (zero overhead quando disattivato) | Nessuno quando disattivato |
openssl_path | (non impostato) | Prefisso di installazione OpenSSL per installazioni non standard (es. /usr/local/ssl) | Nessuno |
Con -Dfips=true, ogni primitiva crittografica rilevante per la sicurezza
viene instradata attraverso un provider FIPS OpenSSL 3.x collegato e validato,
tramite il punto di inserimento crypto_backend, e il simulatore acquisisce
operazioni token PIV post-quantum (firma ML-DSA-65, incapsulamento/disincapsulamento ML-KEM-768)
disponibili solo in modalità FIPS. Il flag è disattivato per impostazione predefinita
con overhead zero; la dipendenza fips viene risolta solo con -Dfips=true.
# Build predefinita — backend std.crypto, nessun collegamento OpenSSL
zig build test
# Build FIPS — provider FIPS OpenSSL (esegui prima `make deps` da fips)
OPENSSL_CONF=/usr/local/ssl/ssl/openssl.cnf \
zig build test -Dfips=true -Dopenssl_path=/usr/local/ssl
# Entrambe le modalità in un colpo solo
make test-dual
Vedi docs/FIPS.md per la progettazione del punto di inserimento,
la politica di esenzione FIPS e le operazioni token PQC.
Nota sulla sicurezza: L'opzione allow_pcsc_env_override è disabilitata per impostazione predefinita per prevenire attacchi di iniezione di librerie dannose (CWE-427). Abilitala solo per sviluppo/test:
# Build di produzione (sicura, variabile d'ambiente ignorata)
zig build
# Build di sviluppo (consente HSM_PCSC_LIB_PATH)
zig build -Dallow_pcsc_env_override=true
Quando abilitate, le librerie vengono validate prima del caricamento:
const std = @import("std");
const hsm = @import("hsm");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Elenca i token disponibili
const tokens = try hsm.listTokens(allocator, false);
defer {
for (tokens) |*t| t.deinit();
allocator.free(tokens);
}
if (tokens.len == 0) {
std.debug.print("Nessun token trovato\n", .{});
return;
}
// Apre il primo token
var token = try hsm.openToken(allocator, tokens[0].id, .{});
defer token.close();
// Verifica il PIN
try token.verifyPin("123456");
// Legge il certificato
const cert = try token.getCertificate(.authentication);
defer allocator.free(cert);
std.debug.print("Certificato: {} byte\n", .{cert.len});
// Firma un digest
var digest: [32]u8 = undefined;
std.crypto.hash.sha2.Sha256.hash("Hello, PIV!", &digest, .{});
const signature = try token.sign(.authentication, .ecdsa_p256, &digest);
defer allocator.free(signature);
std.debug.print("Firma: {} byte\n", .{signature.len});
}
| Tipo | Descrizione |
|---|---|
TokenKind | Tipo di token: .piv, .cac, .yubikey, .unknown |
TokenInfo | Metadati del token scoperto |
Token | Handle token aperto per operazioni |
Slot | Slot chiave: .authentication (9A), .signature (9C), .key_management (9D), .card_auth (9E) |
Algorithm | Algoritmo crittografico: .ecdsa_p256, .ecdsa_p384, .rsa2048_pkcs1v15, ecc. |
Capabilities | Flag delle capacità del token |
PcscScope | Ambito del contesto PC/SC: .user (predefinito), .system |
| Funzione | Descrizione |
|---|---|
listTokens(allocator, use_sim) | Elenca i token disponibili |
openToken(allocator, id, opts) | Apre un token tramite ID |
token.reconnect() | Riconnette al token e resetta lo stato di autenticazione |
token.verifyPin(pin) | Verifica il PIN |
token.changePin(old, new) | Cambia il PIN |
token.unblockPin(puk, new_pin) | Sblocca il PIN con PUK |
token.getCertificate(slot) | Ottiene il certificato in formato DER |
token.sign(slot, alg, digest) | Firma un digest |
token.decrypt(slot, alg, ciphertext) | Decifra dati |
token.capabilities() | Ottiene le capacità del token |
token.close() | Chiude la connessione al token |
Tutte le operazioni restituiscono errori da HsmError:
PcscUnavailable, ReaderGone, CardRemoved, TimeoutPinIncorrect, PinLocked, PinLengthInvalidNotSupported, SlotNotFound, AlgorithmNotSupportedInvalidTlv, CertificateNotFound, InvalidDigestLengthSecurityConditionNotSatisfied, AuthenticationFailed