Certificate Handler
Introduction
The Certificate Handler (CertHandler) is the core module within IAM responsible for managing cryptographic keys and X.509 certificates. It provides a unified interface for creating key pairs, generating Certificate Signing Requests (CSRs), applying signed certificates, and tracking certificate validity — regardless of the underlying storage technology.
CertHandler uses a pluggable module architecture to support different secure storage backends. Each module implements the same HSM interface, allowing the system to work with hardware security modules (via PKCS#11), TPM devices, or filesystem-based storage without changing the certificate management logic.
Architecture
CertHandler is implemented in the aos_core_lib_cpp library and used by the IAM application. It consists of three
layers:
CertHandler (certhandler.hpp)
├── CertModule (certmodule.hpp) # Per-type certificate management
│ ├── HSMItf # Hardware security module interface
│ ├── StorageItf # Certificate metadata storage interface
│ └── x509::ProviderItf # X.509/CSR operations
└── Module implementations
├── PKCS11Module # PKCS#11 cryptographic token
├── TPM Module # TPM 2.0 device
└── Software Module # Filesystem-based storage
CertHandler
The top-level CertHandler class manages a collection of CertModule instances — one per configured certificate type.
It routes operations to the appropriate module based on the certType parameter and notifies registered listeners when
certificates change.
Key responsibilities:
- Module registration and lookup by certificate type
- Thread-safe access to certificate operations (mutex-protected)
- Certificate change notification to subscribed listeners (CM, SM)
- Self-signed certificate creation for initial bootstrap
CertModule
Each CertModule handles certificates of a single type (e.g., "iam", "sm", "cm"). It coordinates between the HSM
interface (for key/certificate storage), the metadata storage interface (for tracking certificate information in the
database), and the X.509 provider (for CSR generation and certificate parsing).
Key responsibilities:
- Key generation via the HSM backend
- CSR creation with configured extensions (extended key usage, alternative DNS names)
- Certificate chain validation
- Certificate application (storing in HSM + recording metadata)
- Certificate trimming (removing oldest certificates when
maxCertificatesis exceeded) - Database synchronization on initialization (reconciling HSM state with stored metadata)
Supported Key Algorithms
CertHandler supports two key generation algorithms, configured per certificate module:
| Algorithm | Description | PKCS#11 Parameters |
|---|---|---|
| RSA | RSA 2048-bit key pairs | 2048-bit modulus length |
| ECDSA | Elliptic Curve Digital Signature Algorithm | P-384 curve (secp384r1) |
The key algorithm is specified in the module configuration via the algorithm field and applies to all keys generated
by that module.
Certificate Lifecycle
Key Creation and CSR Generation
Certificate deployment follows a two-step process:
- CreateKey — the client requests a new key pair. CertHandler generates the key in the configured storage backend and returns a PEM-encoded CSR.
- ApplyCertificate — the client provides the signed certificate (obtained from a CA using the CSR). CertHandler stores the certificate and updates its metadata database.
The CSR includes:
- Subject — the common name provided by the caller (e.g., the Node ID)
- Extended Key Usage — configured per module:
clientAuth,serverAuth, or both - Subject Alternative Names — DNS names configured for server certificates
Certificate Application
When a signed certificate is applied:
- The PEM certificate chain is parsed into X.509 certificate objects
- The certificate chain is validated (each certificate's issuer matches a parent in the chain)
- If the module has reached its
maxCertificateslimit, the oldest certificate (by expiration date) is removed to make room - The certificate is stored in the HSM backend (matched to its pending private key)
- Certificate metadata (type, issuer, serial, URLs, expiration) is recorded in the database
Certificate Retrieval
Certificates are retrieved by specifying:
- Certificate type — identifies which module to query
- Issuer and serial number — identifies a specific certificate
If issuer and serial are empty, CertHandler returns the newest certificate (latest notAfter date) from the specified
module. This is the common case for components requesting their current active certificate.
Certificate locations are expressed as URLs with scheme-specific formats:
pkcs11://...— certificate stored in a PKCS#11 tokentpm://0x80000001— certificate key stored in TPM at the specified handlefile:///var/crypto/cert.pem— certificate stored on the filesystem
Certificate Renewal
Certificate renewal uses the same CreateKey → ApplyCertificate flow as initial deployment. The process is triggered externally (typically by the cloud during scheduled renewal):
- The cloud sends a
CreateKeyrequest via the IAM protected API - IAM generates a new key pair and returns the CSR
- The cloud signs the CSR with the appropriate CA and sends back the certificate via
ApplyCert - IAM applies the new certificate, which becomes the active certificate
- If the certificate count exceeds
maxCertificates, the oldest certificate is automatically removed
The maxCertificates configuration (minimum 2 for non-self-signed modules) ensures that a valid certificate always
exists during renewal — the new certificate is applied before the old one is removed.
Self-Signed Certificates
CertHandler can create self-signed certificates for bootstrap scenarios (before a CA-signed certificate is available). Self-signed certificates:
- Use
CN=Aos Coreas both subject and issuer - Have a validity period of 100 years
- Use the current Unix timestamp (nanoseconds) as the serial number
- Are created through the same key generation and application pipeline
Self-signed modules require maxCertificates of at least 1 (vs. 2 for CA-signed modules).
Certificate Change Notifications
Other components (CM, SM) subscribe to certificate change notifications for specific certificate types. When a
certificate is applied or renewed, CertHandler compares the new certificate info against the last known state for each
subscriber. If the certificate has changed, the subscriber's OnCertChanged callback is invoked with the updated
certificate information.
This mechanism allows components to automatically reload their TLS credentials when certificates are renewed.
Storage Modules
PKCS#11 Module
The PKCS#11 module stores keys and certificates in any hardware or software token that implements the PKCS#11 Cryptographic Token Interface. This provides a unified interface to TPM devices, TEE secure storage, and software HSMs.
Token identification — the module identifies its token by one of:
- Slot ID (unique hardware identifier)
- Slot index (position in the slot list)
- Token label (assigned during initialization)
If configured by label and no initialized token with that label exists, the module initializes the first available uninitialized slot with the configured label.
Object management — PKCS#11 objects (keys, certificates) are identified by:
CKA_ID— links a private key, public key, and certificate togetherCKA_LABEL— set to the storage type, used to distinguish objects when multiple certificate types share a slot
Authentication — token access requires a user PIN, provided via:
- A PIN file (path configured in
userPINPath) - TEE identity (OP-TEE PKCS#11 TA) — uses Linux user/group authentication instead of a PIN
Certificate URLs — follow the PKCS#11 URI scheme (RFC 7512), optionally including the module library path.
Configuration parameters:
| Parameter | Description |
|---|---|
library | Path to the PKCS#11 shared library |
slotId | Slot ID (mutually exclusive with slotIndex and tokenLabel) |
slotIndex | Slot index (mutually exclusive with slotId and tokenLabel) |
tokenLabel | Token label (mutually exclusive with slotId and slotIndex) |
userPinPath | Path to the file containing the user PIN |
teeLoginType | TEE login type: public, user, or group |
uid | User ID for TEE user login type |
gid | Group ID for TEE group login type |
modulePathInURL | Include library path in PKCS#11 URIs |
TPM Module
The TPM module uses a TPM 2.0 device for key storage while storing certificates on the filesystem.
Key storage — keys are generated in the TPM and stored in persistent TPM handles. During key creation, keys are held in a temporary pending storage (up to 16 keys). When a certificate is applied, the matching pending key is moved to a persistent TPM handle.
Ownership — the TPM module supports device ownership. The owner password is set during provisioning and required for key creation and removal. Clearing the module removes the owner password and all stored keys and certificates.
Configuration parameters:
| Parameter | Description |
|---|---|
device | Path to the TPM device |
storagePath | Directory for certificate file storage |
lockoutMaxTry | Maximum authentication failures before lockout |
recoveryTime | Time between authentication failure counter decrements |
lockoutRecoveryTime | Time to recover from lockout |
Software Module
The software module stores both keys and certificates on the filesystem. It is suitable for development and testing environments or systems without hardware security.
Key storage — generated keys are held in RAM (pending key storage, up to 16 keys). When a certificate is applied, the matching key is written to the configured storage directory alongside the certificate.
Certificate hooks — the software module supports a post-apply hook (applyCertHookCmdArgs) — a shell command
executed after each certificate is successfully applied. This enables custom integration (e.g., restarting services that
use the certificate).
Ownership — not supported by the software module.
Configuration parameters:
| Parameter | Description |
|---|---|
storagePath | Directory for key and certificate file storage |
applyCertHookCmdArgs | Shell command executed after certificate application |
Initialization and Validation
On startup, each certificate module performs database synchronization:
- The HSM backend reports all valid certificates, invalid certificates, and invalid keys
- Valid certificates are synchronized with the metadata database:
- Certificates present in the HSM but missing from the database are added
- Certificates present in the database but missing from the HSM are removed
- Invalid certificates and keys are tracked for cleanup during the next key creation
This synchronization ensures the database accurately reflects the actual state of the storage backend, even if certificates were modified outside of IAM (e.g., by external provisioning tools).
Modules with skipValidation enabled bypass this synchronization step (used when the storage backend does not support
validation queries).
Module Configuration
Each certificate module is configured in the IAM configuration file with the following common parameters:
| Parameter | Description |
|---|---|
id | Certificate type identifier (e.g., "iam", "sm", "cm") |
plugin | Module implementation: "pkcs11module", "tpmmodule", or "swmodule" |
algorithm | Key algorithm: "RSA" or "ECDSA" |
maxItems | Maximum number of certificates to retain (minimum 2 for CA-signed, 1 for self-signed) |
extendedKeyUsage | Array of extended key usages: ["clientAuth"], ["serverAuth"], or both |
alternativeNames | DNS alternative names for server certificates |
disabled | Whether the module is disabled |
skipValidation | Skip certificate validation on initialization |
isSelfSigned | Module uses self-signed certificates |
params | Module-specific parameters (PKCS#11, TPM, or software module config) |
gRPC API Integration
CertHandler operations are exposed through the IAM gRPC API:
| gRPC Service | RPC | CertHandler Operation |
|---|---|---|
IAMCertificateService | CreateKey | CertHandler::CreateKey → generates key + CSR |
IAMCertificateService | ApplyCert | CertHandler::ApplyCertificate → stores certificate |
IAMPublicCertService | GetCert | CertHandler::GetCert → retrieves certificate info |
IAMPublicCertService | SubscribeCertChanged | CertHandler::SubscribeListener → certificate change stream |
IAMProvisioningService | StartProvisioning | CertHandler::SetOwner → takes ownership of storage |
IAMProvisioningService | Deprovision | CertHandler::Clear → removes all certificates and keys |
Related Pages
- Identity and Access Manager — IAM overview and architecture
- Provisioning and Enrollment — initial Node setup that establishes certificates
- Node Identity — per-Node identity management
- Certificate Architecture — certificate hierarchy and trust chain
- Hardware Security (PKCS#11) — detailed PKCS#11 integration
- Security Model — broader security architecture context