EPdfPkcs11Error = class(Exception);
TPdfPkcs11Options = record
ModulePath: string;
SlotId: UInt64;
UseSpecificSlot: Boolean;
Pin: string;
CertificateLabel: string;
class function Default: TPdfPkcs11Options; static;
end;
TPdfPkcs11SignerProvider = class(TInterfacedObject, IPadesSignerProvider,
IPdfPkcs11SignerProvider)
constructor Create(const Options: TPdfPkcs11Options);
destructor Destroy; override;
function BackendName: string;
function Resolve(const Options: TPadesSignerOptions): TPadesResolvedSigner;
function EnumerateSlots: TPdfPkcs11Slots;
function EnumerateCertificates(SlotID: UInt64): TPdfPkcs11Certificates;
procedure CloseProtectedSessions;
end;
function Pkcs11ModuleAvailable(const ModulePath: string): Boolean;
function Pkcs11ModuleVersion(const ModulePath: string): string;
function Pkcs11AbiLayout: string;
function ConfigurePkcs11SignerProvider(
const Options: TPdfPkcs11Options): IPdfPkcs11SignerProvider;
FPdfPkcs11 è il backend di firma PAdES portabile e la controparte del backend CNG di Windows. Risolve un certificato del firmatario e la sua chiave privata da un token PKCS#11, poi restituisce un TPadesResolvedSigner il cui ICmsSigner produce la firma SignerInfo attraverso il token, così la chiave non lo lascia mai
Il modulo viene caricato a runtime per percorso - opensc-pkcs11.so, libsofthsm2.so, una DLL di un produttore - quindi nulla viene linkato in fase di build e un modulo assente viene riportato anziché essere fatale. Solo C_GetFunctionList viene risolto per nome; ogni altro entry point proviene dalla tabella di funzioni che restituisce, che è il modo in cui lo standard intende che si raggiunga un modulo
ConfigurePkcs11SignerProvider costruisce un TPdfPkcs11SignerProvider a partire da un valore TPdfPkcs11Options e lo installa come backend di firmatari PAdES attivo, restituendo l'interfaccia IPdfPkcs11SignerProvider che porta anche i metodi di enumerazione del token
Pkcs11ModuleAvailable e Pkcs11ModuleVersion riportano se un dato modulo si carica ed espone una tabella di funzioni utilizzabile, così un'applicazione può decidere all'avvio se la firma via token è possibile su questa macchina. I moduli caricati vengono messi in cache per percorso, perché lo standard consente una sola inizializzazione per processo per modulo
Resolve seleziona il certificato tramite TPadesSignerOptions.CertificateThumbprint quando ne viene fornito uno e tramite CertificateLabel altrimenti, poi individua l'oggetto chiave privata che porta lo stesso identificatore di token del certificato. L'algoritmo della chiave del certificato decide la famiglia di algoritmi: una chiave EC firma con ECDSA e la sua firma raw viene ricodificata nella SEQUENCE DER che CMS si attende, mentre una chiave RSA segue lo schema di padding richiesto
EnumerateSlots e EnumerateCertificates servono alle interfacce utente di selezione, permettendo a un'applicazione di elencare gli slot che un modulo riporta e i certificati che uno slot scelto contiene prima che qualsiasi opzione di firma venga fissata
| Function | Description |
|---|---|
Pkcs11ModuleAvailable | Restituisce True quando il modulo al percorso indicato si carica ed espone una tabella di funzioni utilizzabile |
Pkcs11ModuleVersion | Restituisce la stringa di versione che il modulo riporta, o una stringa vuota quando il modulo non si carica |
Pkcs11AbiLayout | Restituisce il layout ABI che questa build ha risolto, come ulong=<n> attr=<n> pss=<n> table=<n> |
ConfigurePkcs11SignerProvider | Costruisce un provider dalle opzioni fornite, lo installa come backend di firmatari PAdES e lo restituisce come IPdfPkcs11SignerProvider |
| Type | Purpose |
|---|---|
EPdfPkcs11Error | Eccezione sollevata quando non è configurato alcun percorso di modulo, il modulo non può essere caricato, una chiamata al token fallisce, o non viene trovato alcun certificato o chiave privata corrispondente |
TPdfPkcs11Options | Record che nomina il modulo, lo slot, il PIN e il certificato con cui il provider lavora |
TPdfPkcs11SignerProvider | Classe provider che implementa IPadesSignerProvider e IPdfPkcs11SignerProvider sopra un modulo PKCS#11 |
| Field | Description |
|---|---|
ModulePath | Percorso del modulo PKCS#11; richiesto, perché quale modulo serve un token è una decisione di deployment e non esiste un default utile |
SlotId | Slot del token da aprire, onorato solo quando UseSpecificSlot è True |
UseSpecificSlot | Lasciare False per prendere il primo slot che riporta un token presente |
Pin | PIN utente; il provider azzera la propria copia una volta che il token l'ha consumato, e il chiamante resta responsabile del ciclo di vita della stringa che passa |
CertificateLabel | Etichetta di oggetto facoltativa del certificato con cui firmare, usata solo quando TPadesSignerOptions.CertificateThumbprint è vuoto |
Default | Factory statica che restituisce opzioni con percorso di modulo vuoto, slot 0, selezione automatica dello slot, e nessun PIN o etichetta |
| Member | Description |
|---|---|
Create | Costruisce il provider da un valore TPdfPkcs11Options; il modulo stesso viene aperto al primo uso |
Destroy | Chiude ogni sessione di token aperta prima che l'istanza venga rilasciata |
BackendName | Restituisce il nome del backend, con il nome file del modulo aggiunto quando è configurato un percorso di modulo |
Resolve | Risolve TPadesSignerOptions in un TPadesResolvedSigner contenente il firmatario del token e il DER del certificato del firmatario |
EnumerateSlots | Restituisce ogni slot che il modulo riporta come TPdfPkcs11Slots, compresi gli slot senza token presente |
EnumerateCertificates | Restituisce i certificati contenuti in uno slot come TPdfPkcs11Certificates, aprendo prima una sessione su quello slot |
CloseProtectedSessions | Esegue il logout dove è avvenuto un login e chiude la sessione aperta, rilasciando il token ad altri consumatori |
CK_ULONG segue il unsigned long C, quindi è di 4 byte su Windows (LLP64) e 8 byte su Linux e macOS (LP64); ogni handle, conteggio e tipo di attributo è un CK_ULONGPkcs11AbiLayout riporta il layout che questa build ha risolto, così una discrepanza è diagnosticabile anziché un crash silenzioso: Win32 riporta ulong=4 attr=12 pss=12 table=2, Win64 riporta ulong=4 attr=16 pss=12 table=2, e un target LP64 riporta ulong=8 attr=24 pss=24 table=8CertificateLabel vince il primo certificato sul token, adatto a un token con un solo certificato e a nessun deployment di produzione