diff --git a/docs/components.puml b/docs/components.puml new file mode 100644 index 0000000..c325bf9 --- /dev/null +++ b/docs/components.puml @@ -0,0 +1,71 @@ +@startuml +!include +!include + +LAYOUT_TOP_DOWN() + +System_Ext(SignerClient, "Signer client", "Send commands to signer") + +System_Boundary(Signer, "Signer server") { + Boundary(SignerSoftware, "Signer Software") { + Component(SerialHandler, "Serial link handler", "Go", "Reads and writes to the serial interface, parses and creates frames") + Component(ProtocolHandler, "Protocol handler", "Go", "Parses and creates protocol messages") + Component(X509SigningHandler, "X.509 signing", "Go", "Handles X.509 certificate signing commands") + Component(X509RevocationHandler, "X.509 revocation", "Go", "Handles X.509 certificate revocation commands") + Component(OpenPGPSigningHandler, "OpenPGP signing", "Go", Handles OpenPGP key signing commands") + Component(X509CRLHandler, "X.509 crl", "Go", "Handles X.509 CRL retrieval commands") + Component(HealthHandler, "Health check", "Go", "Handles health check commands") + Component(HSMAccess, "HSM access", "Go", "Handles HSM hardware access") + Component(SyncHandler, "Synchronization handler", "Go", "Handles synchronization with other signer") + ComponentDb(SignerDB, "Certificate repository", "Go, Embedded Key-Value DB", $sprite="database") + } + + ContainerQueue(NATS, "NATS Service", "NATS") +} + +System_Boundary(Signer2, "Other signer") { + Boundary(SignerSoftware2, "Signer Software") { + Component_Ext(SyncHandler2, "Synchronization handler", "Go", "Handles synchronization with other signer") + ComponentDb_Ext(SignerDB2, "Certificate repository", "Go, Embedded Key-Value DB", $sprite="database") + } + + ContainerQueue_Ext(NATS2, "NATS Service", "NATS") +} + +Component_Ext(HSM, "HSM", "PKCS#11", "Hardware security module") + +Rel(SignerClient, SerialHandler, "Uses", "USB serial link") + +Rel(SerialHandler, ProtocolHandler, "Uses") + +Rel(ProtocolHandler, X509SigningHandler, "Uses") +Rel(ProtocolHandler, X509CRLHandler, "Uses") +Rel(ProtocolHandler, X509RevocationHandler, "Uses") +Rel(ProtocolHandler, OpenPGPSigningHandler, "Uses") +Rel(ProtocolHandler, HealthHandler, "Uses") + +Rel(X509SigningHandler, HSMAccess, "Uses") +Rel(X509SigningHandler, SignerDB, "Writes") + +Rel(X509RevocationHandler, SignerDB, "Writes") + +Rel(X509CRLHandler, HSMAccess, "Uses") +Rel(X509CRLHandler, SignerDB, "Reads") + +Rel(OpenPGPSigningHandler, HSMAccess, "Uses") +Rel(OpenPGPSigningHandler, SignerDB, "Writes") + +Rel(HealthHandler, HSMAccess, "Checks") +Rel(HealthHandler, SignerDB, "Checks") + +Rel(SyncHandler, SignerDB, "Uses") + +BiRel(SyncHandler, NATS, "Synchronize", "NATS protocol") +BiRel(NATS, NATS2, "Synchronize", "NATS/TLS") +BiRel(SyncHandler2, NATS2, "Synchronize", "NATS protocol") + +Rel(SyncHandler2, SignerDB2, "Uses") + +Rel(HSMAccess, HSM, "Uses", "PKCS#11") + +@enduml \ No newline at end of file diff --git a/docs/components.svg b/docs/components.svg new file mode 100644 index 0000000..8997ebc --- /dev/null +++ b/docs/components.svg @@ -0,0 +1,850 @@ +«boundary»Signer server[System]«boundary»Signer Software«boundary»Other signer[System]«boundary»Signer Software«container»NATS Service[NATS]«component»Serial link handler[Go] Reads and writes to theserial interface, parses andcreates frames«component»Protocol handler[Go] Parses and createsprotocol messages«component»Command dispatcher[Go] Dispatch commands tocommand handlers«component»X.509 signing[Go] Handles X.509 certificatesigning commands«component»X.509 revocation[Go] Handles X.509 certificaterevocation commands«component»OpenPGP signing[Go] Handles OpenPGP keysigning commands"«component»X.509 crl[Go] Handles X.509 CRLretrieval commands«component»Health check[Go] Handles health checkcommands«component»HSM access[Go] Handles HSM hardwareaccess«component»Synchronizationhandler[Go] Handles synchronizationwith other signer«component»Certificate repository[Go, Embedded Key-Value DB]«external_container»NATS Service[NATS]«external_component»Synchronizationhandler[Go] Handles synchronizationwith other signer«external_component»Certificate repository[Go, Embedded Key-Value DB]«external_system»Signer client Send commands to signer«external_component»HSM[PKCS#11] Hardware security moduleUses[USB serial link]UsesUsesUsesUsesUsesUsesUsesUsesWritesWritesUsesReadsUsesWritesChecksChecksUsesSynchronize[NATS protocol]Synchronize[NATS/TLS]Synchronize[NATS protocol]UsesUses[PKCS#11] \ No newline at end of file diff --git a/docs/container.puml b/docs/container.puml new file mode 100644 index 0000000..017b29d --- /dev/null +++ b/docs/container.puml @@ -0,0 +1,34 @@ +@startuml +!include +!include +!include +!include +!include +!include + +Person_Ext(CommunityMember, "Community Member", $sprite="users") + +System_Boundary(Signer, "Signer") { + Container(SignerServer, "Signer Server", "Go binary", "Performs certificate signing", $sprite="go") + ContainerDb(SignerDB, "Certificate repository", "Key-Value DB", $sprite="database") +} + +System_Boundary(Signer2, "Other Signer") { + Container_Ext(SignerServer2, "Signer Server") +} + +System_Boundary(WebDB, "WebDB") { + Container_Ext(WebDBApp, "WebDB application", "PHP", "Provides the user interface for requesting certificates", $sprite="php") + Container_Ext(SignerClient, "Signer Client", "Go binary", "Handle signing request", $sprite="go") + ContainerDb_Ext(DB, "Database", "MySQL/MariaDB", "Hold certificate requests and certificates", $sprite="mysql") +} + +Rel(CommunityMember, WebDBApp, "Uses", "https") +Rel(WebDBApp, DB, "Uses") +Rel(SignerClient, DB, "Uses") +Rel_R(SignerClient, SignerServer, "Uses", "Serial binary protocol") +Rel(SignerServer, SignerDB, "Uses") + +BiRel_R(SignerServer, SignerServer2, "Synchronize", "TLS") + +@enduml \ No newline at end of file diff --git a/docs/container.svg b/docs/container.svg new file mode 100644 index 0000000..63bd925 --- /dev/null +++ b/docs/container.svg @@ -0,0 +1,868 @@ +«boundary»Signer[System]«boundary»Other Signer[System]«boundary»WebDB[System]«container»Signer Server[Go binary] Performs certificate signing«container»Certificate repository[Key-Value DB]«external_container»Signer Server[]«external_container»WebDB application[PHP] Provides the user interfacefor requesting certificates«external_container»Signer Client[Go binary] Handle signing request«external_container»Database[MySQL/MariaDB] Hold certificate requestsand certificates«external_person»Community MemberUses[https]UsesUsesUses[Serial binary protocol]UsesSynchronize[TLS] \ No newline at end of file diff --git a/docs/design.md b/docs/design.md new file mode 100644 index 0000000..e1ba6ad --- /dev/null +++ b/docs/design.md @@ -0,0 +1,151 @@ +# Signer system design + +This document describes the system design of the CAcert signer software. The document describes the integration as well +as technical design decisions. + +## Context + +The signer is used to handle X.509 certificate and OpenPGP public key signing, X.509 certificate revocation and CRL +handling. The signer receives commands via a serial link. + +![C4 Context diagram of the Signer showing the interaction with the surrounding systems described in the sections below](container.svg "Signer Context diagram") + +### WebDB + +*WebDB* is the system running the user facing *WebDB application*. The *Signer client* that is part of the *WebDB* +system, polls certificate and public key signing as well as certificate revocation request information from the +*WebDB database* periodically. The *Signer client* takes care of fetching CRLs and health information from the +*Signer server* periodically. + +The requests are send via a binary protocol (msgpack + COBS) over a serial link. + +*Note:* the database polling may be replaced with an event broker like Redis or NATS in the future. + +### Signer + +The *Signer* system runs the signer software. The system is only reachable via a serial link from the outside. +Information coming over that connection is trusted in the sense that requested certificate attributes where checked by +the requesting *WebDB application*. + +The *Signer Server* synchronizes with another Signer via a dedicated internal network link (crossover cable). The +synchronization is required to make information related to issued and revoked certificates available on both signers. + +## Signer components + +The Signer server is structured into several components with clear responsibilities. + +![C4 Component diagram showing the components of the signer described in the sections below.](components.svg "Components of the signer") + +The Singer server is implemented in [Go](https://golang.org/), configured via YAML and running as a standalone +process. + +### Serial link handler + +The serial link handler handles all communication over the serial link. It reads raw bytes and writes raw bytes, it +handles the serial link and takes care of connection and configuration. + +The raw bytes are framed using +[Consistent Overhead Byte Stuffing (COBS)](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing). + +Frame data consists of msgpack formatted protocol messages and a CRC32 code to ensure integrity. Broken frames are +rejected with an error frame. + +Used libraries: +- [github.com/tarm/serial](https://pkg.go.dev/github.com/tarm/serial) +- [github.com/justincpresley/go-cobs](https://pkg.go.dev/github.com/justincpresley/go-cobs) + +### Protocol handler + +The protocol handler receives [msgpack](https://msgpack.org/) information from the serial link handler and sends +msgpack information to the serial link handler. + +The protocol handler inspects incoming msgpack messages and dispatches the parsed payload to the appropriate command +handler. The result from the command handler is serialized back to a msgpack message and sent to the serial link +handler. + +Used library: +- [github.com/shamaton/msgpackgen](https://pkg.go.dev/github.com/shamaton/msgpackgen) + +*TODO:* the protocol message have to be described in more detail + +### X.509 signing handler + +The X.509 signing handler takes care of X.509 certificate signing. It needs to support certificate profiles. The +profiles decide which attributes from the request are used/accepted, which is private key is used and which extensions +are set in the resulting certificate. + +Actual signing is performed by the *HSM access* component. Signed certificate information is stored in the +*Certificate repository*. + +### X.509 revocation handler + +The X.509 revocation handler takes care of X.509 certificate revocation. It expects an issuer DN and serial number and +supports an optional revocation reason. The revocation handler marks the corresponding certificate as revoked in the +*Certificate repository*. + +*Note:* CRLs are not generated immediately + +### X.509 CRL handler + +The X.509 CRL handler takes care of generating certificate revocation lists. The handler expects an issuer DN, checks +for non-expired, revoked certificates in the *Certificate repository* and generates a CRL. + +The *HSM access* component is used to sign the CRL. + +*TODO:* Clarify whether the CRL should contain expired certificates within a configurable grace period (see RFCs and +potential other reference material for guidance) + +*TODO:* Do we need specific CRLs for specific certificate profiles (i.e. only for server certificates)? + +### OpenPGP signing handler + +The OpenPGP signing handler takes care of OpenPGP key signing. + +Actual signing is performed by the *HSM access* component. Signed OpenPGP key information is stored in the +*Certificate repository*. + +Used library: +- [github.com/ProtonMail/go-crypto/openpgp](https://pkg.go.dev/github.com/ProtonMail/go-crypto/openpgp) + +### Health check handler + +The Health check handler takes care of providing signer health information to the signer client. The health check data +contains: + +- accessibility and consistency information of the *Certificate repository* +- expiry information for the signing certificates +- health information for the HSM +- version information +- current time of the signer + +### HSM access + +The HSM access component provides signing capabilities backed by HSMs (hardware security modules). It uses the PKCS#11 +protocol to access the HSM hardware or SoftHSM. + +Used libraries: +- [github.com/ThalesIgnite/crypto11](https://pkg.go.dev/github.com/ThalesIgnite/crypto11) +- SoftHSM2 (from [Debian package](https://tracker.debian.org/pkg/softhsm2)) +- [OpenSC](https://github.com/OpenSC/OpenSC/wiki) (from [Debian package](https://tracker.debian.org/pkg/opensc)) for + access to [SmartCardHSM or NitroKey HSM](https://github.com/OpenSC/OpenSC/wiki/SmartCardHSM) + +### Certificate repository + +The certificate repository stores information about issued and revoked X.509 certificates as well as signed OpenPGP +keys. + +*TODO:* define the data format for the certificate repository + +Used library: +- [github.com/dgraph-io/badger/v3](https://pkg.go.dev/github.com/dgraph-io/badger/v3) + +### Synchronization handler + +The synchronization handler is used to synchronize state (signing, revocation and CRL issuing information) between +signers. The handler acts as a producer and consumer for synchronization messages. The message transport should use +a lightweight existing middleware like [NATS](https://nats.io/). + +The synchronization handler may require support for replaying messages when a signer comes back after a service +interruption or when a new signer is set up. + +*TODO:* specify the synchronization protocol in much more detail \ No newline at end of file