Keys and certificates
Many different keys and certificates are used by all of Fobnail's components. Most of them are automatically generated, but some must be provided by user.
List of keys and certificates used
Refer to architecture doc for description of actors and phases listed below. List items have the following format:
- Name of key or certificate
- Phase during which it is obtained, received or used
- Other details, if any
Note that this list includes possible usages that may not be implemented yet.
Platform Owner
Knows in advance
- Platform Owner key (signing and encryption)
- Fobnail and remote platform provisioning
- used for TLS and for signing certificates
- Platform Owner certificate
- Fobnail and remote platform provisioning
- has to be able to provide whole CA chain
- both Fobnail Token and Platform must trust root CA in this chain
- root CA certificate for EK certificate chain
- remote platform provisioning
Receives
- Fobnail Identity key
- Fobnail provisioning
- Fobnail Encryption key
- Fobnail provisioning
- EK certificate
- remote platform provisioning
- AIK
- remote platform provisioning
Produces
- Fobnail Identity certificate
- Fobnail provisioning
- Fobnail Encryption certificate
- Fobnail provisioning
- AIK certificate
- remote platform provisioning
- simple signature instead of certificate may be sufficient
Fobnail Token
Knows in advance
- root CA certificate for EK certificate chain
- local platform provisioning
- root CA for Platform Owner certificate chain
- Fobnail provisioning
Receives
- Platform Owner certificate chain
- Fobnail provisioning
- saved in flash, used in local platform provisioning and attestation
- Fobnail Identity certificate
- Fobnail provisioning
- signed by Platform Owner
- Fobnail Encryption certificate
- Fobnail provisioning
- signed by Platform Owner
- EK certificate
- local platform provisioning
- AIK
- local platform provisioning
- remote platform provisioning - signed by Platform Owner
- stored in flash and used during attestation
Produces
- Fobnail Identity key (signing and encryption)
- Fobnail provisioning
- key and certificate signed by Platform Owner is stored for later use
- Fobnail Encryption key (encryption)
- Fobnail provisioning
Platform
Knows in advance
- root CA for Platform Owner certificate chain
- remote platform provisioning
- local platform provisioning and attestation - Fobnail Identity key is signed by Platform Owner, so Platform needs a way of verifying trust chain
- Endorsement Key (encryption)
- remote and local platform provisioning
- for this project may be considered immutable persistent key unique to TPM
- EK certificate
- EK is unique so is its certificate
- usually saved in TPM NVRAM
- signed by TPM manufacturer CA
Receives
- Platform Owner certificate chain
- remote platform provisioning - directly from Platform Owner
- local platform provisioning and attestation - from Fobnail Token
- used for identification, TLS and verifying Fobnail Identity certificate
- Fobnail Identity certificate
- local platform provisioning and attestation
- used for identification and TLS
Produces
- Attester Identity Key (signing)
- local and remote platform provisioning
- created by TPM
- trusted based on Make/ActivateCredential and pairing with EK instead of certificate
Platform Owner certificate chain
Platform Owner trust chain uses X.509 certificates, usually in PEM format. It aims to be compatible with standard Public Key Infrastructure, as described in RFCs 5280 or 3647, among others. At least basic understanding of PKI is strongly suggested, but if you just want to quickly test Fobnail, you may just do steps in TL;DR section.
Platform Owner certificate is used during Fobnail provisioning. Its root CA certificate must be preinstalled on Fobnail Token. Due to limited hardware capabilities of Fobnail Token, following restrictions apply.
Validity checks
Informational checks
-
Maximum certificate chain length
Maximal supported certificate chain consists of 3 CA certificates: root CA (flashed to Fobnail's memory), intermediate CA and final CA that is used to issue certificates for keys generated by Fobnail. Intermediate CA is optional, root and issuing CA aren't. During Fobnail provisioning, Platform Owner generates one additional certificate for Token, but this final certificate doesn't allow for use as a CA.
This limit comes from hardware limitations (in terms of available memory) aggravated by chosen library (Trussed) and its limitations.
-
File format
Certificates are concatenated to a single PEM file. Order of concatenation matters, certificates must be written starting with root CA certificate and moving through intermediate towards leaf certificate. All of them must be present, despite the fact that root CA is already known by Fobnail.
-
Certificate extensions
Trust chain will be traversed based on
X509v3 Authority Key Identifier
extension which is compared againstX509v3 Subject Key Identifier
, so both of them must be included in every certificate (former should be skipped for root CA).X509v3 Basic Constraints
is required for CA certificates.X509v3 Key Usage
must specify that all certificates in Platform Owner chain are able to sign certificates.
Temporal checks
- Validity period
Reference Fobnail Token (nRF52840 dongle) has no timekeeping capabilities. Because of that, validity period cannot be tested without adding another party that Fobnail Token trusts, or by using another dongle for Fobnail Token.
- Certificate revocation
Fobnail Token doesn't have trusted network connection, so it can't access recent (i.e. one that happened after last firmware update) certificate revocation list at run time. Revocations can only be applied during flashing/update, which should be done by Platform Owner. During that process, attempt to use revoked certificates should result in failed provisioning.
Creating Platform Owner certificate chain with OpenSSL
This section describes how to create a certificate chain that conforms to restrictions mentioned earlier. This is just a minimal example showing all required configuration options and commands used in the process, fields listed here may be extended or modified, but should not be removed. Normally CAs do much more than what is presented here, some guidelines can be found in RFC 3647.
Note that root CA doesn't have to be under Platform Owner's control, but it must issue a certificate that is (either directly or through intermediate issuer). In such cases the issuer may use other form of certificate request or additional mechanisms of proving the identity of the requester than those used by OpenSSL.
Root CA
Root CA certificate is self-signed. This means that signed public and signing
private keys belong to the same pair, and no exchange of data between separate
entities happens. -x509
parameter tells that this is the case and a
self-signed certificate is to be made, instead of CSR (Certificate Signing
Request).
-
First create configuration file
root_ca.cfg
, for example:[ req ] distinguished_name = req_distinguished_name prompt = no x509_extensions = v3_ext [ req_distinguished_name ] C = PL O = Fobnail ST = State CN = Platform Owner root CA certificate [v3_ext] basicConstraints = critical, CA:TRUE, pathlen:3 keyUsage = critical, keyCertSign, cRLSign subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always
Feel free to adjust configuration to your needs.
-
Run command:
openssl req -newkey rsa:2048 -nodes -keyout root_ca_priv.pem -x509 -days 365 \ -out root.crt -config root_ca.cfg
root_ca_priv.pem
- newly created private root CA key. Keep it safe.root.crt
- root CA certificate. This will be hardcoded and marked as trusted by Fobnail Token.
Intermediate/PO issuing CA
Note: "PO issuing CA" in this part of the document should be understood as the CA that issues certificate requested by Fobnail Token. In general, each certificate has its own issuer. If that meaning of the word is required, "higher-level CA", "intermediate CA" or "root CA" is used.
These certificates aren't self-signed. Creation of such certificates consists of two steps: first one is generating a CSR (Certificate Signing Request) and is done by key creator, second one is creating the certificate itself - this is done by the parent CA. This separation is done to keep private keys secret at all times.
Steps for both intermediate and issuing CA certificates are mostly the same, the main difference is that CSR for intermediate is sent to root CA, and PO issuing CA's CSR is sent to intermediate CA. This chain can be longer in general, but Fobnail limits maximum length, as mentioned above. Intermediate CA is optional, PO issuing CA certificate can be signed by root CA directly.
Before issuing a certificate, issuer must check if subject is authorized to ask for it. It can't just blindly provide a new certificate to anyone that asks for it, because by creating a signed certificate CA tells others that it trusts its subject. Trust decision can be based on fields of CSR, challenge password, secure and non-public way of conveying CSR to issuer, or other means. Sometimes the decision is made by another entity called Registration Authority (RA) on behalf of CA.
In this case because subject of each signed certificate is itself a CA and can create certificates for other entities. Certificate revocation for Fobnail can't be done by means other than firmware updates, so issuing a certificate to untrustworthy subject impacts not only the security of devices provisioned by issuer, but also every device with the same root CA.
Generating intermediate CA key and CSR
This is similar to creating root CA with two small but important differences:
-x509
flag is not used in the command linex509_extensions
are not present (those are added by the issuer)
Command executed by intermediate CA:
openssl req -newkey rsa:2048 -nodes -keyout intermediate_priv_key.pem
-out intermediate.csr -config intermediate.cfg
intermediate_priv_key.pem
(out) - newly created private intermediate CA key. Keep it safe.intermediate.csr
(out) - intermediate CA certificate signing request. This file is signed with private intermediate CA key by above command and must be passed to root CA.intermediate.cfg
(in) - configuration file, e.g.:
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
C = PL
O = Fobnail
ST = State
CN = Intermediate CA certificate
Generating intermediate CA certificate
openssl ca
can also be used for this purpose, butopenssl x509
is easier to use for single chain. On the other hand,openssl ca
better suits the needs of CA after configuration and may do more checks in semi-automatic process thanopenssl x509
.
Command executed by root CA:
openssl x509 -req -in intermediate.csr -CA root.crt -CAkey root_ca_priv.pem \
-CAcreateserial -days 365 -extfile intermediate.ext -out intermediate.crt
intermediate.csr
(in) - sent by intermediate CA.root.crt
androot_ca_priv.pem
(in) - those were created by root CA earlier.intermediate.crt
(out) - intermediate CA certificate signed with root CA keyroot_ca_priv.pem
.intermediate.ext
(in) - file describing certificate extensions, e.g.:
basicConstraints = critical, CA:TRUE, pathlen:2
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
Generating PO issuer CA key and CSR
Command executed by PO issuer CA:
openssl req -newkey rsa:2048 -nodes -keyout root_ca_priv.pem -out issuer.csr \
-config issuer.cfg
root_ca_priv.pem
(out) - newly created private PO issuing CA key. Keep it safe.issuer.csr
(out) - PO issuing CA certificate signing request. This file is signed with private PO issuing CA key by above command and must be passed to intermediate CA.issuer.cfg
(in) - configuration file, e.g.:
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
C = PL
O = Fobnail
ST = State
CN = Platform Owner issuer CA certificate
Generating PO issuer CA certificate
Command executed by intermediate CA:
openssl x509 -req -in issuer.csr -CA $AUTHORITY_CERT -CAkey $AUTHORITY_PRIV \
-CAcreateserial -days 365 -extfile $SUBJECT_EXT -out $SUBJECT_CERT
issuer.csr
(in) - sent by PO issuer CA.intermediate_priv_key.pem
(in) - created by intermediate CA earlier.intermediate.crt
(in) - issued by root CA in response to request from intermediate CA.issuer.crt
(out) - PO issuer CA certificate signed withintermediate_priv_key.pem
.issuer.ext
(in) - file describing certificate extensions, e.g.:
basicConstraints = critical, CA:TRUE, pathlen:1
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
Putting the chain together
PEM files contain certificates (among other objects that are not relevant here)
encoded as text. They can be concatenated e.g. with cat
to form a chain. As
mentioned above, the order of certificates matters:
leaf (i.e. PO issuing certificate) must come first, root CA - last. Assuming
*.crt
files are PEM certificates of various CAs, full chain is produced by:
cat root.crt intermediate.crt issuer.crt > cert_chain.pem
TL;DR version
While it is strongly suggested to understand and follow steps described above, these steps can be used to produce a chain that will be accepted by Fobnail. It can be used to quickly build and test Fobnail project, but such approach defies the idea of Fobnail provisioning and Platform Owner in general. It should not be used on Tokens for production environments.
-
Create root CA key and certificate:
openssl req -newkey rsa:2048 -nodes -keyout root_ca_priv.pem -x509 -days 30 -out root_ca.crt -config <(cat << EOF [ req ] distinguished_name = req_distinguished_name prompt = no x509_extensions = v3_ext [ req_distinguished_name ] C = PL O = Fobnail ST = State CN = Platform Owner root CA certificate [v3_ext] basicConstraints = critical, CA:TRUE, pathlen:2 keyUsage = critical, keyCertSign, cRLSign subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always EOF )
-
Create PO issuing CA private key and CSR:
openssl req -newkey rsa:2048 -nodes -keyout po_priv_key.pem \ -out issuer_ca.csr -config <(cat << EOF [ req ] distinguished_name = req_distinguished_name prompt = no [ req_distinguished_name ] C = PL O = Fobnail ST = State CN = Platform Owner issuer CA certificate EOF )
-
Create PO issuing CA certificate:
openssl x509 -req -in issuer_ca.csr -CA root_ca.crt -CAcreateserial \ -CAkey root_ca_priv.pem -days 30 -out issuer_ca.crt \ -extfile <(cat << EOF basicConstraints = critical, CA:TRUE, pathlen:1 keyUsage = critical, keyCertSign, cRLSign subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always EOF )
-
Create chain from both certificates:
cat root_ca.crt issuer_ca.crt > cert_chain.pem