EPdfKeychainError = class(Exception);
TPdfKeychainSignerProvider = class(TInterfacedObject, IPadesSignerProvider)
constructor Create(const KeychainPath: string = '');
function BackendName: string;
function Resolve(const Options: TPadesSignerOptions): TPadesResolvedSigner;
end;
TPdfKeychainCmsVerifier = class(TInterfacedObject, IPdfCmsVerifier)
function BackendName: string;
function VerifyDetached(const CmsDer: TBytes; Segment1: Pointer; Segment1Length: Cardinal; Segment2: Pointer; Segment2Length: Cardinal; const Options: TPdfCmsVerifyOptions): TPdfCmsVerifyResult;
function VerifyAttached(const CmsDer: TBytes; const Options: TPdfCmsVerifyOptions): TPdfCmsVerifyResult;
end;
function KeychainAvailable: Boolean;
function KeychainMissingSymbols: string;
function KeychainVerificationAvailable: Boolean;
function ConfigureKeychainSignerProvider: IPadesSignerProvider;
function ConfigureKeychainCmsVerifier: IPdfCmsVerifier;
procedure ConfigureKeychainTrustAnchors(const Anchors: TPadesChainCertArray);
procedure ConfigureKeychainOcspResponses(const Responses: TPadesChainCertArray);
FPdfCryptoMac is the macOS crypto backend consumed by FPdfCrypto and FPdfCms, and it covers both halves of the platform integration: PAdES signing through a Keychain identity, and CMS verification through the system CMS decoder and trust evaluation. Security.framework and CoreFoundation are loaded and their symbols resolved by name at run time rather than linked, so the unit compiles for every target and reports at run time whether the platform services are actually reachable
On the signing side, TPdfKeychainSignerProvider implements IPadesSignerProvider. Its Resolve method enumerates the Keychain identities, selects the one whose certificate matches the SHA-1 thumbprint carried by TPadesSignerOptions, reads the certificate DER and the matching private key reference, and returns a TPadesResolvedSigner whose ICmsSigner signs the CMS signed attributes through Security.framework, so the private key never leaves the Keychain. The padding scheme requested through the options is reconciled with what the key can actually do, and the RSASSA-PSS parameters are the same ones the other backends emit, so a document signed on macOS carries an identical AlgorithmIdentifier. ConfigureKeychainSignerProvider builds the provider and installs it as the active PAdES signing backend, returning the interface it registered
On the verification side, TPdfKeychainCmsVerifier implements IPdfCmsVerifier on top of CMSDecoder and SecTrust. VerifyDetached joins the two signed byte ranges either side of the signature hole into the detached content the decoder expects, then verifies the CMS value against it; VerifyAttached verifies a CMS value that carries its own content, which is what a timestamp token requires. Both return a TPdfCmsVerifyResult that reports signature status, trust status and revocation status separately whilst optionally collecting the signer certificate and the evaluated chain, and both honour the revocation, online retrieval and checkpoint settings in TPdfCmsVerifyOptions. ConfigureKeychainCmsVerifier builds the verifier and installs it as the active CMS verification backend
Signature validity and certificate trust remain independent results, so an authentic signature under an untrusted or self-signed chain remains distinguishable from tampered content
For attached RFC 3161 tokens, size-limited DER parsing passes the original encapsulated TSTInfo octets to the native decoder, leaving content type and signed attributes intact. Ordinary CMS checks remove unsigned attributes from native input so automatic timestamp handling cannot override the outer signature's integrity or chain verdict. Countersignatures and other unsigned attributes are outside that pass; ValidatePadesTrust independently checks each original timestamp token, its imprint, TSA role, trust and revocation
Give TPdfKeychainSignerProvider.Create a Keychain file path to confine identity lookup to that Keychain using a query-local search list, then register it with ConfigurePadesSignerProvider. An empty path retains the current user search scope. Opening or querying the selected Keychain leaves the default Keychain, user search list and system trust unchanged; invalid paths or missing scoped-search symbols raise EPdfKeychainError
Resolve also exports the signing certificate's available issuer chain, using offline certificate lookup confined to the query and native chain construction. Candidate certificates are limited to 4096 entries, 1 MiB each and 16 MiB altogether; the resulting chain is limited to 32 certificates including the leaf, which is returned separately from ChainCertDer. Exporting these certificates neither establishes trust nor installs a trust anchor, and a missing issuer cannot be synthesised
| Function | Description |
|---|---|
KeychainAvailable | Returns True when Security.framework and CoreFoundation have loaded and every symbol required for signing has been resolved |
KeychainMissingSymbols | Returns the names that failed to resolve, separated by spaces, or an empty string when everything bound successfully |
ConfigureKeychainSignerProvider | Builds a TPdfKeychainSignerProvider, installs it as the PAdES signing backend, and returns it as an IPadesSignerProvider |
TPdfKeychainSignerProvider.Create | Optionally selects an existing Keychain file for restricted identity lookup; embedded NUL characters and paths exceeding 4096 string code units are refused |
TPdfKeychainSignerProvider.BackendName | Returns the backend identifier reported for the signing provider |
TPdfKeychainSignerProvider.Resolve | Matches TPadesSignerOptions against the Keychain identities and returns a TPadesResolvedSigner holding the signer, the certificate DER and the chain |
| Function | Description |
|---|---|
KeychainVerificationAvailable | Returns True when the CMS decoder, trust policy and trust evaluation symbols have resolved |
ConfigureKeychainCmsVerifier | Builds a TPdfKeychainCmsVerifier, installs it as the CMS verification backend, and returns it as an IPdfCmsVerifier |
ConfigureKeychainTrustAnchors | Copies explicit DER anchors for later trust evaluations, supplementing system anchors without changing the Keychain; permits 64 certificates, 4 MiB each and 16 MiB overall, with an empty array clearing them |
ConfigureKeychainOcspResponses | Copies supplied DER OCSP evidence for native Security.framework checks; permits 8 responses, 1 MiB each and 4 MiB overall, with an empty array clearing them |
TPdfKeychainCmsVerifier.BackendName | Returns the backend identifier reported for the verification backend |
TPdfKeychainCmsVerifier.VerifyDetached | Verifies a detached CMS value against the two caller-owned content segments described by Segment1, Segment1Length, Segment2 and Segment2Length, using the supplied TPdfCmsVerifyOptions |
TPdfKeychainCmsVerifier.VerifyAttached | Verifies an attached CMS value that carries its own signed content, using the supplied TPdfCmsVerifyOptions |
| Type | Members and purpose |
|---|---|
EPdfKeychainError | Exception raised when Security.framework is unavailable, when no Keychain identity matches the requested signer, or when the platform signing call fails |
TPdfKeychainSignerProvider | PAdES signing backend implementing IPadesSignerProvider, with BackendName and Resolve |
TPdfKeychainCmsVerifier | CMS verification backend implementing IPdfCmsVerifier, with BackendName, VerifyDetached and VerifyAttached |
KeychainAvailable and KeychainVerificationAvailable report signing and verification separately because the two halves need different framework symbols, so a system can bind one and not the otherKeychainMissingSymbols names every symbol that failed to resolve, which is what makes an absent framework distinguishable from a binding problem: an empty result means everything bound successfully, a result naming the framework paths means the frameworks did not load, and a result naming individual entry points means the frameworks loaded but a name did not resolveKeychainAvailable and KeychainVerificationAvailable, an empty KeychainMissingSymbols, and EPdfKeychainError from configuration functionsTPadesSignerOptions carries no certificate thumbprint the first usable identity in the Keychain is selected, which suits a test rather than a production signaturepcvsUnsupported, rather than valid or invalid integrity; use the OpenSSL CMS verifier instead. Mixed signer diagnostics retain separate algorithm results for every signerFreshOcspResponse DER and time filter, then native responder signature, authority and certificate checks; skew is limited to 300 seconds, and producedAt and thisUpdate may be no more than one day oldOnlineRetrieval=False turns off native trust-network fetching. Online Security.framework evaluation follows the platform's behaviour; this backend does not give UrlRetrievalTimeoutMs the limited OpenSSL transport deadlineCollectSignerDiagnostics=True returns individual snapshots up to MaxSignerCount and the hard ceiling of 64; returned certificate data is capped at 4 MiB each and 64 MiB overall, with unfinished collection reported as pcvsIndeterminateSignerDiagnosticsStatus=pcvsValid signifies complete collection, including failed signer decisions; RevocationError holds native Security.framework status and RevocationCertificate remains empty here