Apache HTTP Server
The following example shows how to set up Apache2 (httpd) HTTP server to work with the OpenSSLv3 pkcs11-provider.
Preparation and Prerequisites
-
Make sure that Primus HSM PKCS#11 Provider is installed in your system following the PKCS#11 Provider instructions.
Confirm the successful installation by executing the following test command and checking the output:
ppin -t
Load config file: '/etc/primus/primus.cfg'
hsm0: Connect to 'grimsel.securosys.ch' on port 2410, firmware: RX-3.1.0-T
slot0 (id=0), user=<your partition name>: OK
Number of tested HSMs: 1 (number of partitions: 1)
Number of failures: 0 -
Make sure that the Securosys OpenSSL pkcs11-provider is installed on your system, as it is described on the Quickstart.
-
Make sure that your OpenSSL version is aligned with the Prerequisites.
-
Configure your OpenSSL according to Configuration.
Click to see a configuration example
HOME = .
# Use this in order to automatically load providers.
openssl_conf = openssl_init
# Comment out the next line to ignore configuration errors
config_diagnostics = 1
oid_section = new_oids
[ new_oids ]
[openssl_init]
providers = provider_sect
[random_sect]
random = PKCS11-RAND
[provider_sect]
default = default_sect
base = base_sect
pkcs11 = pkcs11_section
[base_sect]
activate = 1
[default_sect]
activate = 1
[pkcs11_section]
module = /opt/openssl-3.3.2/lib/ossl-modules/pkcs11.so
pkcs11-module-path = /usr/local/primus/lib/libprimusP11.so
pkcs11-module-load-behavior = early
pkcs11-module-quirks = no-deinit no-operation-state
activate = 1
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem # The private key
x509_extensions = usr_cert # The extensions to add to the cert
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extensions to add to the self-signed cert
string_mask = utf8only
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
# SET-ex3 = SET extension number 3
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
basicConstraints=CA:FALSE
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:truenoteIf you haven't installed natively openssl, you might need to configure the below environment variables:
export LD_LIBRARY_PATH=path to the OpenSSL libraries:$LD_LIBRARY_PATH
export OPENSSL_DIR=path to the installation directory for OpenSSL
Install Apache2 (httpd)
Update the package list and install Apache2 if not previously installed:
On RHEL/CentOS the webserver is named httpd instead of apache2. The below command sequences are shown for Ubuntu only.
Ubuntu/Debian
sudo apt update
sudo apt install apache2
Verify that you have at least Version 2.4.62 (or newer) on your system:
apache2 -v
Server version: Apache/2.4.62 (Ubuntu)
Server built: 2024-08-15T07:32:14
Preparing the key and certificate to be used
For this example a simple self-signed certificate is created. For real applications you probably want to get your certificate signed by a CA and put the certificate chain into the cert.pem-file.
Again some environment variables are set-up as placeholders.
export P11_TOKEN=<YOUR_USER_NAME> # partition name
export P11_PIN=<YOUR_PKCS#11_PIN> # hsm pkcs11 pin (don't use for production)
export P11_KEY_NAME=TESTING_APACHE2_KEY # name of Key
A RSA-4096 private key is generated
openssl genpkey -propquery "provider=pkcs11" \
-algorithm "rsa" -pkeyopt "rsa_keygen_bits:4096" \
-pkeyopt "pkcs11_uri:pkcs11:token=${P11_TOKEN};object=${P11_KEY_NAME}?pin-value=${P11_PIN}"
Given the encoder of the OpenSSL pkcs11-provider is enabled, the key will be outputted as a "PKCS#11 PROVIDER URI" pem file.
Use the key to create a self signed certificate
sudo openssl req -new -x509 -copy_extensions=copyall \
-key "pkcs11:type=private;token=${P11_TOKEN};object=${P11_KEY_NAME}?pin-value=${P11_PIN}" \
-subj "/C=CH/ST=Bern/L=Bern/O=My Example Organisation/OU=IT Department/CN=www.example.com" \
-addext "subjectAltName = DNS:www.example.com, DNS:*.www.example.com" \
-sha256 -days 99 -out /etc/apache2/ssl/p11-provider-cert.pem
Adapt the site configuration to use the key from the HSM
Ensure that your web-site is running well using a local key/certificate from file before changing to private key loaded from the HSM.
sudo vi /etc/apache2/sites-available/<your-site.conf>
...
# Certificate from local file
SSLCertificateFile /etc/apache2/ssl/p11-provider-cert.pem
# Private key from Primus HSM or CloudsHSM
SSLCertificateKeyFile "pkcs11:token=<your-partition>;pin-value=<pkcs11-pin>;object=<key-label>;type=private"
...
Test the configuration
Perform a configuration test and verify that no errors are reported.
apachectl configtest
Start the apache service
sudo systemctl daemon-reload
sudo systemctl restart apache2
Webserver optimization for HSM access
If the network connection to the HSM has high latency (e.g. CloudsHSM), it is important to parallelize HSM requests.
Based on our experience, mpm_prefork achieves better results than mpm_event module.
Note that Apache2 performance tuning requires profound knowledge of the apache webserver, mechanisms and configuration.
Click to expand
Performance optimization for mpm_event:
vi /etc/apache2/mods-enabled/mpm_event.conf
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
Performance optimization for mpm_prefork:
vi /etc/apache2/mods-enabled/mpm_prefork.conf
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
To change from mpm_event to mpm_prefork:
sudo a2dismod mpm_event
sudo a2dismod mpm_worker
sudo a2enmod mpm_prefork
sudo systemctl restart apache2
apache2ctl -V | grep MPM