Certificate & Key Setup
1. Introduction
This document is meant for the coordinator, auditors and developers of a Sharemind HI solution. It explains the certificate hierarchy and describes how keys and certificates are created for the coordinator, stakeholders and dynamic end users to enable role based authentication.
2. Certificate Hierarchy
Sharemind HI uses a custom CA hierarchy with ECC P-256 keys and X509 certificates. The X509 certificates contain custom V3 extensions. The CA hierarchy is described in the following picture. The root certificate is hard coded into the enclave and equal across all uses of Sharemind HI. All other keys need to be recreated for each new setup of Sharemind HI (don’t reuse keys across multiple instances of Sharemind HI).
The following is a list of details concerning each of the certificates:
- Sharemind HI Root CA
-
This certificate is owned by Cybernetica. The certificate is hard coded into core enclave and key enclave. The core enclave refuses to boot if the deployment certificate is not signed by the Sharemind HI Root CA certificate.
- Deployment/Coordinator CA
-
This certificate is owned by the coordinator and needs to be signed by the Sharemind HI Root CA certificate. It needs to be accessible to the Sharemind HI Server on startup, and its location is configured in the server configuration file (
server.yaml
). - Stakeholder n
-
Each stakeholder (including the enforcers) needs their own private key and certificate, the latter being signed by the coordinator certificate. These certificates contain special V3 extensions:
1.3.6.1.4.1.3516.17.1.1
-
A
NULL
type, its existence indicates that the Sharemind HI specific V3 extensions are of version 1. 1.3.6.1.4.1.3516.17.1.1.1
-
An
INTEGER
type, specifying which roles the stakeholder is allowed to be assigned to in the DFC. The DFC can assign the stakeholder to less roles, but not to more roles (more details in Section 3.2).
The stakeholder certificates need to be shared as follows:
-
Stakeholders configure their private key and certificate in the configuration of their Sharemind HI Client, and they need to share the certificate through an authenticated channel with enforcers.
-
Enforcers share their certificate through an authenticated channel with the other stakeholders, who need to configure them as their trusted enforcers.
-
The Coordinator gathers all stakeholder certificates and configures them in the dataflow configuration
dfc.yaml
, which is read by the Sharemind HI Server on startup.
- CA Stakeholder n
-
All details of the stakeholder key and certificate apply to the CA stakeholders as well. The only distinction is that these certificates have X509 attributes configured to sign an additional level of certificates. Additionally, they are not allowed to contain the Input Provider, Runner nor Data Consumer roles.
- Dynamic End User n
-
These certificates are only used by the dynamic end user themselves (but can be shared if necessary, e.g. to implement custom access control rules in the task enclave). These certificates contain special V3 extensions:
1.3.6.1.4.1.3516.17.1.1
-
A
NULL
type, its existence indicates that the Sharemind HI specific V3 extensions are of version 1 (same as for stakeholder certificates). 1.3.6.1.4.1.3516.17.1.1.2
-
An
OCTET STRING
type, containing the ACII encoded name of one end-entity role from the dataflow configuration.
3. Coordinator Instructions
The coordinator needs to setup an intermediate certificate authority (CA).
The public key certificate needs to be signed by the Cybernetica Deployment Root CA for Sharemind HI deployments.
With the intermediate CA the coordinator then signs the stakeholder’s certificate signing requests.
Each stakeholder certificate will then contain the stakeholder’s common name and its assigned roles.
3.1. Creating the Coordinator CA
If the coordinator has already set up a CA then this section can be skipped. The later code examples need to be adapted for the existing CA.
To create a new CA we use OpenSSL. First, a new directory and some required content is created.
ca_path="$(mkdir -p "/path/to/new/ca/directory")"
mkdir -p "$ca_path/certs" "$ca_path/crl" "$ca_path/newcerts"
touch "$ca_path/index.txt" "$ca_path/index.txt.attr"
echo "1000" > "$ca_path/crlnumber"
echo "1000" > "$ca_path/serial"
Additionally, the following config is required for further usage.
cat <<EOF > "$ca_path/openssl.cnf"
oid_section = ext_oids
[ ext_oids ]
sharemind_hi_client_extensions_v1 = 1.3.6.1.4.1.3516.17.1.1
sharemind_hi_client_extensions_v1_roles = 1.3.6.1.4.1.3516.17.1.1.1
################################################################################
# CA Definition
[ ca ]
default_ca = ca_intermediate
################################################################################
# Per the above, this is where we define CA values
[ ca_intermediate ]
dir = .
certs = \$dir/certs
crl_dir = \$dir/crl
new_certs_dir = \$dir/newcerts
database = \$dir/index.txt
serial = \$dir/serial
crlnumber = \$dir/crlnumber
private_key = \$dir/intermediate.key
certificate = \$dir/intermediate.crt
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 1000
preserve = no
policy = policy_loose
unique_subject = no
################################################################################
# The default policy for the CA when signing requests.
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
################################################################################
# Define how to generate CSRs
[ req ]
default_bits = 4096
string_mask = utf8only
default_md = sha256
distinguished_name = req_distinguished_name
################################################################################
# Per "req" section, this is where we define DN info
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, your name or your server hostname)
commonName_max = 64
emailAddress = Email Address ## Print this message
emailAddress_max = 64
EOF
Now the private key and certificate signing request (CSR) need to be generated:
# (Disable password protection by omitting the `-aes-128-cbc` argument)
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes-128-cbc -out "$ca_path/intermediate.key"
# Interactive. The common name is required.
openssl req -new -config "$ca_path/openssl.cnf" -key "$ca_path/intermediate.key" -out "$ca_path/intermediate.csr"
# (Optional) Inspect the certificate signing request:
openssl req -in "$ca_path/intermediate.csr" -noout -text
The generated $ca_path/intermediate.csr
needs to be sent to Cybernetica.
Cybernetica will sign it with the deployment root CA and send it back in two forms:
-
As a signed certificate which needs to be stored as
$ca_path/intermediate.crt
. -
As a certificate chain which needs to be accessible to
sharemind-hi-server
during startup. The path to this file needs to be configured in the server configuration’sDeploymentRootCertificateFile
field.
3.2. Signing Stakeholder CSRs
Signing the CSR of a stakeholder first requires to calculate a natural number which encodes the roles of that stakeholder. This natural number is the sum of the respective role IDs which are listed in the following table. For example, for a stakeholder with the roles of an Enforcer and Input Provider the calculated number is 3. Note that CA stakeholders can only be Enforcer and Auditor.
Role | ID | Regular Stakeholder | CA Stakeholder |
---|---|---|---|
Enforcer |
1 |
Yes |
Yes |
Input Provider |
2 |
Yes |
No |
Runner |
4 |
Yes |
No |
Data Consumer |
8 |
Yes |
No |
Auditor |
32 |
Yes |
Yes |
The calculated number is then used in the following OpenSSL stakeholder configuration $stakeholder_cnf
.
Note that the extensions depend on whether you sign a regular stakeholder or a CA stakeholder.
# For regular stakeholders
[ ext_stakeholder ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid, issuer
basicConstraints = critical, CA:false
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
# Sharemind HI specific OID
1.3.6.1.4.1.3516.17.1.1 = ASN1:NULL
# example: Enforcer and Input Provider
# 1.3.6.1.4.1.3516.17.1.1.1 = ASN1:INTEGER:3
1.3.6.1.4.1.3516.17.1.1.1 = ASN1:INTEGER:<Calculated Number>
# For CA stakeholders
[ ext_ca_stakeholder ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid, issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, \
dataEncipherment, cRLSign, keyCertSign
# Sharemind HI specific OID
1.3.6.1.4.1.3516.17.1.1 = ASN1:NULL
# example: Enforcer and Auditor
# 1.3.6.1.4.1.3516.17.1.1.1 = ASN1:INTEGER:33
1.3.6.1.4.1.3516.17.1.1.1 = ASN1:INTEGER:<Calculated Number>
Assuming the stakeholder’s CSR is stored at $stakeholder_csr
, the contents of the CSR should be reviewed.
Especially the Common Name field shall be inspected for correctness, as well as the public key algorithm using prime256v1
.
openssl req -in "$stakeholder_csr" -noout -text -verify
If the CSR is correct, the stakeholder certificate can be created at $stakeholder_crt
.
The -days
argument which specifies how many days the certificate is valid should be modified for the deployment at hand.
cd "$ca_path"
# Is it a regular stakeholder, or a CA stakeholder?
extensions="ext_stakeholder" # regular stakeholder
extensions="ext_ca_stakeholder" # ca stakeholder
openssl ca -batch -config "openssl.cnf" -name ca_intermediate \
-extfile "$stakeholder_cnf" -extensions "$extensions" \
-notext -in "$stakeholder_csr" -out "$stakeholder_crt" -days 1000
$stakeholder_crt
needs to be sent back to the respective stakeholder.
Also, these stakeholder certificates are used in the dataflow configuration which is added by the Coordinator (or the server host), so the Coordinator should keep a copy of $stakeholder_crt
.
4. Regular Stakeholder & Dynamic End User Instructions
Creating the Private Key and Certificate
The user needs to create a public-key cryptography key pair. Note: A user must use their key pair only in a single Sharemind HI deployment and never reuse their key pair for any other purpose. If a user wants to participate in a Sharemind HI deployment for different analytics, they must generate a new key pair. The key pair must be based on the NIST P-256 curve. This elliptic curve is enforced by the Intel® SGX SDK.
# Creates encrypted PKCS8 key with a passphrase entered via an interactive prompt.
# (Disable password protection by omitting the `-aes-128-cbc` argument)
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes-128-cbc -out user.key
# OpenSSL already applies the required file permissions:
# chmod go-rwx user.key
Using an encrypted private key requires to provide the passphrase whenever the sharemind-hi-client
application is run, as explained in the man page description for the --passphrase-file
argument.
Password protection can be disabled by omitting the -aes-128-cbc
argument.
The private key needs to be accompanied by a X509 certificate which is signed with the deployment certificate by the Coordinator for regular stakeholders, or signed by a CA stakeholder for dynamic end users.
This certificate will also encode the roles of the user.
The roles are configured by the Coordinator or a CA Stakeholder, not by the user.
Therefore, the user needs to generate a certificate signing request (CSR).
This process is interactive.
The important configuration is Common Name
which should clearly identify the user.
This field will be verified by the Coordinator or CA stakeholder.
openssl req -new -key "user.key" -out "user.csr"
user.csr
needs to be sent to the Coordinator or CA stakeholder.
The Coordinator will return a certificate.
The user needs to check that the received certificate matches the private key, which can be done using the following method:
# Verify that both commands produce the same output.
openssl pkey -in "user.key" -pubout | openssl sha256
openssl x509 -in "/path/to/received/user.crt" -pubkey -noout | openssl sha256
If the user uses sharemind-hi-client
, user.key
and the received certificate need to be pointed to in the client.yaml
client configuration (PrivateKeyFile
and PublicKeyCertificateFile
, respectively).
Enforcers need to share their certificate over an authenticated channel with the input providers, output consumers and optionally task runners. This is required to create a link of trust between the enforcers who verify the dataflow configuration and the other users who interact with the dataflow configuration. This authenticated channel can be for example a vis-à-vis meeting to exchange and verifying the certificate, or it can be created using the signing functionality of the Estonian ID card.
Note: Please remember the above mentioned requirement to never reuse a key pair across different Sharemind HI deployments, or for any other purpose.
5. CA Stakeholder Instructions
5.1. Creating the Stakeholder CA
A stakeholder which wants to act as a CA (a CA stakeholder) can use OpenSSL to manage the signing process of CSRs from dynamic end users. First, a new directory and some required content is created.
ca_path="$(mkdir -p "/path/to/new/ca/directory")"
mkdir -p "$ca_path/certs" "$ca_path/crl" "$ca_path/newcerts"
touch "$ca_path/index.txt" "$ca_path/index.txt.attr"
echo "1000" > "$ca_path/crlnumber"
echo "1000" > "$ca_path/serial"
Additionally, the following config is required for further usage.
cat <<EOF > "$ca_path/openssl.cnf"
oid_section = ext_oids
[ ext_oids ]
sharemind_hi_client_extensions_v1 = 1.3.6.1.4.1.3516.17.1.1
sharemind_hi_client_extensions_v1_end_entity_roles = 1.3.6.1.4.1.3516.17.1.1.2
################################################################################
# CA Definition
[ ca ]
default_ca = ca_intermediate
################################################################################
# Per the above, this is where we define CA values
[ ca_intermediate ]
dir = .
certs = \$dir/certs
crl_dir = \$dir/crl
new_certs_dir = \$dir/newcerts
database = \$dir/index.txt
serial = \$dir/serial
crlnumber = \$dir/crlnumber
private_key = \$dir/intermediate.key
certificate = \$dir/intermediate.crt
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 1000
preserve = no
policy = policy_loose
unique_subject = no
################################################################################
# The default policy for the CA when signing requests.
[ policy_loose ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
################################################################################
# Define how to generate CSRs
[ req ]
default_bits = 4096
string_mask = utf8only
default_md = sha256
distinguished_name = req_distinguished_name
################################################################################
# Per "req" section, this is where we define DN info
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, your name or your server hostname)
commonName_max = 64
emailAddress = Email Address ## Print this message
emailAddress_max = 64
EOF
Now the private key and certificate signing request (CSR) need to be generated:
# (Disable password protection by omitting the `-aes-128-cbc` argument)
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes-128-cbc -out "$ca_path/intermediate.key"
# Interactive. The common name is required.
openssl req -new -config "$ca_path/openssl.cnf" -key "$ca_path/intermediate.key" -out "$ca_path/intermediate.csr"
# (Optional) Inspect the certificate signing request:
openssl req -in "$ca_path/intermediate.csr" -noout -text
The generated $ca_path/intermediate.csr
needs to be sent to Cybernetica.
Cybernetica will sign it with the deployment root CA and send it back in two forms:
-
As a signed certificate which needs to be stored as
$ca_path/intermediate.crt
and sent to the Coordinator, such that they add it to the dataflow configuration.
5.2. Signing Dynamic End User CSRs
This action is performed by a CA stakeholder.
Signing the CSR of a dynamic end user first requires to determine which end-entity role from the dataflow configuration to assign to the user.
The role name is then encoded in the certificate as shown in the following OpenSSL user configuration $user_cnf
(OpenSSL encodes the string as ASCII by default).
[ ext_dynamic_end_user ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid, issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
# Sharemind HI specific OID
1.3.6.1.4.1.3516.17.1.1 = ASN1:NULL
# example: End-Entity role name is "ee-producer"
# 1.3.6.1.4.1.3516.17.1.1.2 = ASN1:OCTETSTRING:ee-producer
1.3.6.1.4.1.3516.17.1.1.2 = ASN1:OCTETSTRING:<end-entity name from the DFC>
Assuming the CSR of the dynamic end user is stored at $user_csr
, the contents of the CSR should be reviewed.
Especially the Common Name field shall be inspected for correctness, as well as the public key algorithm using prime256v1
.
openssl req -in "$user_csr" -noout -text -verify
If the CSR is correct, the user certificate can be created at $user_crt
.
The -days
argument which specifies how many days the certificate is valid should be modified for the deployment at hand.
cd "$ca_path"
openssl ca -batch -config "openssl.cnf" -name ca_intermediate -extfile "$user_cnf" -extensions ext_dynamic_end_user -notext -in "$user_csr" -out "$user_crt" -days 1000
$user_crt
needs to be sent back to the respective user.
Note that this certificate does not need to be registered in the dataflow configuration.
It can be used right away.