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 -tLoad config file: '/etc/primus/primus.cfg'hsm0: Connect to 'grimsel.securosys.ch' on port 2410, firmware: RX-3.1.0-Tslot0 (id=0), user=<your partition name>: OKNumber 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 errorsconfig_diagnostics = 1oid_section = new_oids[ new_oids ][openssl_init]providers = provider_sect[random_sect]random = PKCS11-RAND[provider_sect]default = default_sectbase = base_sectpkcs11 = pkcs11_section[base_sect]activate = 1[default_sect]activate = 1[pkcs11_section]module = /opt/openssl-3.3.2/lib/ossl-modules/pkcs11.sopkcs11-module-path = /usr/local/primus/lib/libprimusP11.sopkcs11-module-load-behavior = earlypkcs11-module-quirks = no-deinit no-operation-stateactivate = 1####################################################################[ ca ]default_ca = CA_default # The default ca section####################################################################[ CA_default ]dir = ./demoCA # Where everything is keptcerts = $dir/certs # Where the issued certs are keptcrl_dir = $dir/crl # Where the issued crl are keptdatabase = $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 certificateserial = $dir/serial # The current serial numbercrlnumber = $dir/crlnumber # the current crl number# must be commented out to leave a V1 CRLcrl = $dir/crl.pem # The current CRLprivate_key = $dir/private/cakey.pem # The private keyx509_extensions = usr_cert # The extensions to add to the certname_opt = ca_default # Subject Name optionscert_opt = ca_default # Certificate field optionsdefault_days = 365 # how long to certify fordefault_crl_days= 30 # how long before next CRLdefault_md = default # use public key default MDpreserve = no # keep passed DN orderingpolicy = policy_match# For the CA policy[ policy_match ]countryName = matchstateOrProvinceName = matchorganizationName = matchorganizationalUnitName = optionalcommonName = suppliedemailAddress = optional# For the 'anything' policy# At this point in time, you must list all acceptable 'object'# types.[ policy_anything ]countryName = optionalstateOrProvinceName = optionallocalityName = optionalorganizationName = optionalorganizationalUnitName = optionalcommonName = suppliedemailAddress = optional####################################################################[ req ]default_bits = 2048default_keyfile = privkey.pemdistinguished_name = req_distinguished_nameattributes = req_attributesx509_extensions = v3_ca # The extensions to add to the self-signed certstring_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 = AUcountryName_min = 2countryName_max = 2stateOrProvinceName = State or Province Name (full name)stateOrProvinceName_default = Some-StatelocalityName = Locality Name (eg, city)0.organizationName = Organization Name (eg, company)0.organizationName_default = Internet Widgits Pty LtdorganizationalUnitName = Organizational Unit Name (eg, section)#organizationalUnitName_default =commonName = Common Name (e.g. server FQDN or YOUR name)commonName_max = 64emailAddress = Email AddressemailAddress_max = 64# SET-ex3 = SET extension number 3[ req_attributes ]challengePassword = A challenge passwordchallengePassword_min = 4challengePassword_max = 20unstructuredName = An optional company name[ usr_cert ]basicConstraints=CA:FALSE# PKIX recommendations harmless if included in all certificates.subjectKeyIdentifier=hashauthorityKeyIdentifier=keyid,issuer[ v3_req ]basicConstraints = CA:FALSEkeyUsage = nonRepudiation, digitalSignature, keyEncipherment[ v3_ca ]# Extensions for a typical CA# PKIX recommendation.subjectKeyIdentifier=hashauthorityKeyIdentifier=keyid:always,issuerbasicConstraints = 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_PATHexport 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 CloudHSM
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. CloudHSM), 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